JUC - thread pool

Let me talk about thought first

Pooling technology is a design idea:

Create and reserve resources in advance to avoid wasting CPU resources due to frequent creation and destruction of resources.

Common scenarios:

  • Thread Pool
  • object pool
  • connection pool

Three methods of thread pool


single thread pool

public static void main(String[] args) {
    
    
    //创建单一(大小)线程池
    ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
    try {
    
    
        for(int i = 1;i <= 10; i++){
    
    
            //利用线程池创建线程
            singleThreadExecutor.execute(()->{
    
    
                System.out.println(Thread.currentThread().getName());
            });
        }
    } finally {
    
    
        //关闭线程池
        singleThreadExecutor.shutdown();
    }
}

Results of the:

insert image description here


Customize the number of thread pool threads

public static void main(String[] args) {
    
    
    //创建大小为 5 的线程池
    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
    try {
    
    
        for(int i = 1;i <= 10; i++){
    
    
            //利用线程池创建线程
            fixedThreadPool.execute(()->{
    
    
                System.out.println(Thread.currentThread().getName());
            });
        }
    } finally {
    
    
        //关闭线程池
        fixedThreadPool.shutdown();
    }
}

Results of the:
Custom thread pool thread number execution result


The number of threads in the thread pool is not limited (only affected by the device)

public static void main(String[] args) {
    
       
    //创建大小可变的线程池
	ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    try {
    
    
        for(int i = 1;i <= 10; i++){
    
    
            //利用线程池创建线程
            cachedThreadPool.execute(()->{
    
    
                System.out.println(Thread.currentThread().getName());
            });
        }
    } finally {
    
    
        //关闭线程池
        cachedThreadPool.shutdown();
    }
}

Results of the:
Unlimited thread pool execution results

Three methods of source code review

//单一
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>());
}

All three of them call the ThreadPoolExecutor method:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    
    
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

Then ThreadPoolExecutor calls another construction method of its own:

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.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

At this point, we can find that, in fact, the three methods of the thread pool mentioned at the beginning are just a further simple encapsulation of ThreadPoolExecutor

Simple encapsulation is not very meaningful. Although it can save a few lines of code, it makes the code look unintuitive and comes with security risks.

So we have to define the thread pool ourselves, which is both intuitive and safe.

Custom thread pool (recommended)

//自定义线程池 ThreadPoolExecutor,这样创建比较安全,并且容易阅读

/**最大线程数到底如何定义
 * CPU 密集型: 逻辑处理核数 是几就是几
 * 获得CPU核数
 * System.out.println(Runtime.getRuntime().availableProcessors());
 *
 * IO 密集型: 最大线程数 一定要大于 项目中非常占资源的IO任务数
 * (这样就能保证,在所有IO任务执行的时候,不会阻塞其他的进程执行。)
 */


//CPU密集型的写法(创建自定义线程池)
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        2,//正在营业的
        Runtime.getRuntime().availableProcessors(),//最多营业人数
        3,//3秒钟没人来,(5-2)这3个人就休息了
        TimeUnit.SECONDS,//等待时间单位
        new LinkedBlockingQueue<>(4),//候客区
        Executors.defaultThreadFactory(),//线程创建工程
        //new ThreadPoolExecutor.AbortPolicy()//默认拒绝策略:人满了(max_5 + queue_3 = 8_承载量)再来就抛出异常。
        //new ThreadPoolExecutor.CallerRunsPolicy()//哪来的去哪里,(这里是从 main线程过来的,所以超出的进程会被打回main线程)
        //new ThreadPoolExecutor.DiscardPolicy()//队列满了不会抛出异常,直接不管了(丢掉任务)
        new ThreadPoolExecutor.DiscardOldestPolicy()//队列满了不会抛出异常,但会尝试去和最早的线程竞争。
);
try {
    
    
    for (int i = 1; i <= 5; i++) {
    
    
        threadPoolExecutor.execute(()->{
    
    
            try {
    
    
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        });
    }
} finally {
    
    
    threadPoolExecutor.shutdown();
}

Guess you like

Origin blog.csdn.net/weixin_43415201/article/details/117258156