java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java的ThreadPoolExecutor

Java中的线程池ThreadPoolExecutor细致讲解

作者:y_initiate

这篇文章主要介绍了Java中的线程池ThreadPoolExecutor细致讲解,线程池是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如MySQL,线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,需要的朋友可以参考下

1. 线程池状态

线程池的shutdown()方法,将线程池由RUNNING转为SHUTDOWN状态

线程池的shutdownNow()方法,将线程池由RUNNING或SHUTDOWN转为STOP状态

SHUTDOWN和STOP状态最终都会变为TERMINATED

2. ThreadPoolExecutor构造函数

ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat(“export_data_pool_factory” + “-%d”).build();
ExecutorService pool = new ThreadPoolExecutor(5, 10,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(500), factory, new ThreadPoolExecutor.CallerRunsPolicy());

3. 线程池工作原理

3.1 任务执行流程

注: execute()无返回值发生异常会抛出 submit()返回值为Feature,异常无感知需要通过返回的Feature获取异常信息

当调用线程池execute()或者submit() 方法向线程池提交一个任务时,线程池会做如下判断:

注:此处网上教程为『如果有空闲线程,则直接执行该任务; 如果没有空闲线程,且当前运行的线程数少于corePoolSize,则创建新的线程执行该任务』 但是 ThreadPoolExecutor 的官方注释:“When a new task is submitted in method {@link #execute(Runnable)}, and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle”,经测试官方注释正确

package test;


import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.io.*;
import java.util.*;
import java.util.concurrent.*;

public class Test1 {
    private final ExecutorService pool;

    {
        ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("test_pool_factory" + "-%d").build();
        pool = new ThreadPoolExecutor(3, 5,
                1000L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(10), factory, new ThreadPoolExecutor.CallerRunsPolicy());
    }

    public void close() {
        this.pool.shutdown();
    }

    public void runTask(int i) {
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("index:" + i + " id:" + Thread.currentThread().getId() + " poolSize: " + ((ThreadPoolExecutor)pool).getPoolSize() + "  activeSize:" + ((ThreadPoolExecutor)pool).getActiveCount());
                    System.out.println("index:" + i + " id:" + Thread.currentThread().getId() + " name:" + Thread.currentThread().getName());
                    System.out.println("===============================================");
                } catch (Exception e) {
                    System.out.printf("ERROR: id:%s name:%s time:%s ERROR### \n", Thread.currentThread().getId(), Thread.currentThread().getName(), new Date());
                }
            }
        });
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        Test1 t = new Test1();
        for (int i = 0; i < 5; i++) {
            System.out.println("poolSize:" + ((ThreadPoolExecutor)t.pool).getPoolSize() + " activeSize:" + ((ThreadPoolExecutor)t.pool).getActiveCount());
            t.runTask(i);
            Thread.sleep(100);
        }
        t.close();

    }
}

请添加图片描述

通过运行结果可以看到,任务执行完毕后poolSize已经有线程,并且都处于空闲状态,但当poolSize<corePoolSize时每次都会新建一个线程执行任务

3.2 空闲线程释放策略

当线程空闲时间超过keepAliveTime时,如果线程池设置了allowCoreThreadTimeout参数为true(默认false)则直接释放掉该线程(它最终会收缩到0),如果没有设置则判断当前线程数 > corePoolSize,则该线程会被释放掉(它最终会收缩到 corePoolSize 的大小)。

3.3 任务队列(workQueue)

任务队列:决定了缓存任务的排队策略

ThreadPoolExecutor线程池推荐了三种等待队列,SynchronousQueue 、LinkedBlockQueue和 ArrayBlockingQueue

3.4 threadFactory

threadFactory :指定创建线程的工厂。(可以不指定) 如果不指定线程工厂时,ThreadPoolExecutor 会使用ThreadPoolExecutor.defaultThreadFactory 创建线程。默认工厂创建的线程:同属于相同的线程组,具有同为 Thread.NORM_PRIORITY 的优先级,以及名为 “pool-XXX-thread-” 的线程名(XXX为创建线程时顺序序号),且创建的线程都是非守护进程。

3.5 handler 拒绝策略

handler :表示当 workQueue 已满,且池中的线程数达到 maximumPoolSize 时,线程池拒绝添加新任务时采取的策略。(可以不指定)

4. 常用方法

除了修改创建线程池参数的修改allowCoreThreadTimeOut(boolean value),setKeepAliveTime(long timt, TimeUnit unit),setMaximumPoolSize(int maximumPoolSize),setCorePoolSize(int corePoolSize),setThreadFactory(ThreadFactory threadFactory),setRejectedExecutionHandler(RejectedExecutionHandler handler)外

到此这篇关于Java中的线程池ThreadPoolExecutor细致讲解的文章就介绍到这了,更多相关Java的ThreadPoolExecutor内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文