zoukankan      html  css  js  c++  java
  • 线程、线程池三大方法、七大参数、四种策略

    线程和进程

    进程: 一个程序,是执行程序的一次执行过程。

    一个进程往往包含若干个线程,线程是cpu调度和执行的单位。

    Java默认有2个线程:main、GC

    并发:(多线程操作同一个资源)

    • CPU 一核,模拟出来多条线程,快速交替

    并行:(多个人一起行走)

    • CPU 多核,多个线程可以同时执行;线程池
    public class Test1 {
        public static void main(String[] args) {
            //获取cpu的核数
            //cpu 密集型,IO密集型
            System.out.println(Runtime.getRuntime().availableProcessors());
        }
    }
    

    线程有几种状态

    public enum State {
            // 新生
            NEW,
    
            // 运行
            RUNNABLE,
    
            // 阻塞
            BLOCKED,
    
            // 等待
            WAITING,
    
            // 超时等待
            TIMED_WAITING,
    
            // 终止
            TERMINATED;
    }
    

    wait/sleep 区别

    1、来自不同的类

    wait => Object

    sleep => Thread

    2、关于锁的释放

    wait 会释放锁,sleep 睡觉了,抱着锁睡觉,不会释放!

    3、使用的范围是不同的

    wait:必须在同步代码块中

    sleep:可以在任何地方睡

    Callable接口

    在这里插入图片描述
    1、可以有返回值

    2、可以抛出异常

    3、方法不同,run() / call()

    线程启动只能使用new Thread().start();而Thread类的构造方法只接受Runnable接口;

    FutureTask<V>是Runnable的实现类,并且有构造方法参数为Callable接口。

    所以可以通过类FutureTask来作为Thread的参数启动线程。

    public class CallableTest {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            MyThread thread = new MyThread();
            FutureTask futureTask = new FutureTask(thread); // 适配类
            new Thread(futureTask, "A").start();
            new Thread(futureTask, "B").start();
            
            // 结果只打印一个 call()
            // 结果会被缓存,效率高
            Integer o = (Integer) futureTask.get();
            //这个get 方法可能会产生阻塞!把他放到 最后
            // 或者使用异步通信来处理!
            System.out.println(o);
        }
    }
    
    class MyThread implements Callable<Integer> {
        @Override
        public Integer call() {
            System.out.println("call()");
            return 1024;
        }
    }
    

    1、有缓存

    2、结果可能需要等待,会阻塞!

    线程池

    线程池:三大方法、七大参数、4种拒绝策略

    池化技术

    程序的运行,本质:占用系统的资源!优化资源的技术 ===> 池化技术

    线程池、连接池、内存池、对象池。。。。创建、销毁。十分浪费资源

    池化技术:事先准备好一些资源,有人要用,就来池子里拿,用完之后还过来。

    线程池的好处:

    1、降低资源的浪费

    2、提高响应的速度

    3、方便管理。

    线程复用、可以控制最大并发数、管理线程

    线程池:三大方法

    // Executors 工具类、3大方法
    public class ExecutorsDemo {
        public static void main(String[] args) {
            // ExecutorService threadPool = Executors.newSingleThreadExecutor();// 单个线程
            // ExecutorService threadPool = Executors.newFixedThreadPool(5);// 创建一个固定的线程池的大小
            ExecutorService threadPool = Executors.newCachedThreadPool();// 可伸缩的,遇强则强,遇弱则弱
    
            try {
                for (int i = 1; i <= 100; i++) {
                    // 使用了线程池之后,使用线程池类创建线程
                    threadPool.execute(() -> {
                        System.out.println(Thread.currentThread().getName() + "---OK");
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 线程池用完,程序结束,关闭线程池
                threadPool.shutdown();
            }
        }
    }
    

    三大方法的线程数

    ExecutorService threadPool = Executors.newSingleThreadExecutor();// 单个线程
    ExecutorService threadPool = Executors.newFixedThreadPool(5);// 创建一个固定的线程池的大小
    ExecutorService threadPool = Executors.newCachedThreadPool();// 可伸缩的,遇强则强,遇弱则弱

    三大方法源码分析

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    

    七大参数

    通过三大方法的源码可发现:本质都是通过ThreadPoolExecutor

    // 本质ThreadPoolExecutor()
    
    public ThreadPoolExecutor(int corePoolSize,			// 核心线程池大小
                              int maximumPoolSize,		// 最大核心线程池大小
                              long keepAliveTime,		// 超时没有人调用就会释放
                              TimeUnit unit,			// 超时单位
                              BlockingQueue<Runnable> workQueue,	// 阻塞队列
                              ThreadFactory threadFactory,	//线程工厂:创建线程的,一般不用动
                              RejectedExecutionHandler handler) {	//拒绝策略
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
            null :
        AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
    

    在这里插入图片描述
    在这里插入图片描述

    举例,银行共有5个窗口(最大线程数),有常开的两个窗口处理业务(核心线程数);候客区(阻塞队列)有三个位置;当两个常开窗口(核心线程)以及候客区(阻塞队列)的位置都有人后,再来客户会开启另外三个窗口;当5个窗口(最大线程)和候客区(阻塞队列)都有人后,再来客户会启动拒绝策略。当窗口(线程)超过设定时间(超时时间)没有业务办理时(未调用)会关闭窗口(释放线程)。

    // Executors 工具类、3大方法
    
    /**
     * new ThreadPoolExecutor.AbortPolicy() // 银行满了,还有人进来,不处理这个人的,抛出异 常
     * new ThreadPoolExecutor.CallerRunsPolicy() // 哪来的去哪里!
     * new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!
     * new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会 抛出异常!
     */
    public class ExecutorsDemo01 {
        public static void main(String[] args) {
            // 自定义线程池!工作ThreadPoolExecutor
            ExecutorService threadPool = new ThreadPoolExecutor(
                    2,
                    5,
                    3,
                    TimeUnit.SECONDS,
                    new LinkedBlockingDeque<>(3),
                    Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.DiscardOldestPolicy()); //队列满了,尝试去和 最早的竞争,也不会抛出异常!
            try {
                // 最大承载:Deque + max
                // 超过 RejectedExecutionException
                for (int i = 1; i <= 9; i++) {
                    // 使用了线程池之后,使用线程池来创建线程
                    threadPool.execute(() -> {
                        System.out.println(Thread.currentThread().getName() + " ok");
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 线程池用完,程序结束,关闭线程池
                threadPool.shutdown();
            }
        }
    }
    

    四种策略

    在这里插入图片描述

    new ThreadPoolExecutor.AbortPolicy() // 银行满了,还有人进来,不处理这个人的,抛出异常

    new ThreadPoolExecutor.CallerRunsPolicy() // 哪来的去哪里!

    new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!

    new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!

    小结和拓展

    问题:池的线程最大值如何去设置!

    了解:IO密集型,CPU密集型(调优)

    最大线程到底该如何定义

    1、CPU 密集型,几核的计算机就设置为几,可以保存CPU的效率最高!

    自动获取计算机CPU处理器个数Runtime.getRuntime().availableProcessors()

    2、IO 密集型 —> 判断程序中十分耗IO的线程,根据IO线程数来设定。

    比如:15个大型IO线程任务,可以最大线程数为30

    =========================

    工作机会(内部推荐):发送邮件至gaoyabing@126.com,看到会帮转内部HR。

    邮件标题:X姓名X_X公司X_简历(如:张三_东方财富_简历),否则一律垃圾邮件!

    公司信息:

    1. 1.东方财富|上海徐汇、南京|微信客户端查看职位(可自助提交信息,微信打开);
  • 相关阅读:
    如何在google官方网站下载测试版、开发版(Beta、Dev)离线安装包?
    Google Chrome 开发进度 官方Blog
    如何在google官方网站下载正式版(Stable)离线安装包?
    asp 毫秒数 timer 当前0点与当前时间的毫秒差
    JavaScript toFixed() 方法
    sqlserver 数据库 SQL循环语句
    IE里Iframe的Cookie问题解决办法总结
    js cookie
    IIS 限制上传大小的问题 200k (SWFUpload_ASP操作的时候更改了本身的限制,还需要更改iis的大小)
    SWFUpload免费FLASH上传组件(ASP修改版)
  • 原文地址:https://www.cnblogs.com/Chary/p/14363152.html
Copyright © 2011-2022 走看看