java线程池

144 阅读6分钟

前言

The main pool control state, ctl, is an atomic integer packing two conceptual fields workerCount, indicating the effective number of threads runState, indicating whether running, shutting down etc In order to pack them into one int, we limit workerCount to (2^29)-1 (about 500 million) threads rather than (2^31)-1 (2 billion) otherwise representable. If this is ever an issue in the future, the variable can be changed to be an AtomicLong, and the shift/mask constants below adjusted. But until the need arises, this code is a bit faster and simpler using an int. The workerCount is the number of workers that have been permitted to start and not permitted to stop. The value may be transiently different from the actual number of live threads, for example when a ThreadFactory fails to create a thread when asked, and when exiting threads are still performing bookkeeping before terminating. The user-visible pool size is reported as the current size of the workers set. The runState provides the main lifecycle control, taking on values: RUNNING: Accept new tasks and process queued tasks SHUTDOWN: Don't accept new tasks, but process queued tasks STOP: Don't accept new tasks, don't process queued tasks, and interrupt in-progress tasks TIDYING: All tasks have terminated, workerCount is zero, the thread transitioning to state TIDYING will run the terminated() hook method TERMINATED: terminated() has completed The numerical order among these values matters, to allow ordered comparisons. The runState monotonically increases over time, but need not hit each state. The transitions are: RUNNING -> SHUTDOWN On invocation of shutdown(), perhaps implicitly in finalize() (RUNNING or SHUTDOWN) -> STOP On invocation of shutdownNow() SHUTDOWN -> TIDYING When both queue and pool are empty STOP -> TIDYING When pool is empty TIDYING -> TERMINATED When the terminated() hook method has completed Threads waiting in awaitTermination() will return when the state reaches TERMINATED. Detecting the transition from SHUTDOWN to TIDYING is less straightforward than you'd like because the queue may become empty after non-empty and vice versa during SHUTDOWN state, but we can only terminate if, after seeing that it is empty, we see that workerCount is 0 (which sometimes entails a recheck -- see below)
ctl 是一个原子整型(AtomicInteger),
封装了两个核心概念字段:
‌workerCount‌:有效工作线程数(最大支持约5亿线程) (2^29-1)  (低29位)
‌runState‌:线程池运行状态(如运行中、关闭中等)(高3位)

Java 线程池的 5 种运行状态‌

  • ‌RUNNING (运行中)‌
‌特点‌: 线程池初始化后的默认状态,可接受新任务并处理队列中的任务
‌触发条件‌: 线程池创建后自动进入此状态
  • ‌SHUTDOWN (关闭)
‌特点‌: 不再接受新任务,但会继续处理队列中已存在的任务
‌触发条件‌: 调用 shutdown() 方法后进入此状态
  • ‌STOP (停止)‌
‌特点‌: 立即拒绝新任务,丢弃队列中的未处理任务,并中断正在执行的任务
‌触发条件‌: 调用 shutdownNow() 方法后进入此状态
  • ‌TIDYING (清理中)‌
‌特点‌: 所有任务已终止(包括队列任务和正在执行的任务),活动线程数降为 0,准备执行终止钩子方法 terminated()
‌触发条件‌:
从 ‌SHUTDOWN‌ 状态转换:任务队列为空且活动线程数为0
从 ‌STOP‌ 状态转换:活动线程数为0
  • ‌TERMINATED (终止)‌
‌特点‌: 线程池彻底终止,terminated() 方法执行完毕
‌触发条件‌: 从 ‌TIDYING‌ 状态转换,执行完 terminated() 方法后
  • 整体流程
RUNNINGSHUTDOWNTIDYINGTERMINATEDSTOPTIDYINGTERMINATED
	
调用 shutdown() 触发 ‌RUNNINGSHUTDOWN‌
调用 shutdownNow() 触发 ‌RUNNING/SHUTDOWNSTOP‌
任务全部处理完毕且线程数为0时触发 ‌SHUTDOWN/STOPTIDYING

ThreadPoolExecutor核心参数

 corePoolSize: 核心线程数
 maximumPoolSize: 最大线程数
 keepAliveTime: 非核心线程数的最大存活时间
 TimeUnit: 存活时间的单位
 BlockingQueue: 队列
 ThreadFactory: 创建线程的工厂
 RejectedExecutionHandler: 拒绝策略

执行过程

   当提交任务到线程池的时候,判断线程池是否运行,如果运行,
   判断核心线程数是否已满,未满创建核心线程数,已满,判断队列
   是否已满,未满加入队列,队列已满,判断线程数是否大于最大线程数
   ,不大于最大线程数,创建线程,大于最大线程数,触发拒绝策略

队列

线程池中的队列(BlockingQueue)用于存储待执行的任务,
当核心线程繁忙时,新任务会进入队列等待,队列的选择直接影响线程池的行为和性能
  • ‌LinkedBlockingQueue
基于链表,默认无界(容量为 Integer.MAX_VALUE),可指定容量,任务量稳定,需平衡吞吐量与内存
  • ‌ArrayBlockingQueue‌
基于数组,必须指定固定容量,严格 FIFO,需严格控制队列大小的场景
  • SynchronousQueue
不存储任务,直接移交任务给线程(需匹配生产者与消费者),高吞吐量,任务处理速度快
  • PriorityBlockingQueue
支持优先级排序的无界队列,需按优先级处理任务的场景
  • 核心方法
add()	添加元素,队列满时抛出 IllegalStateException	
offer()	添加元素,队列满时返回 false
put()	阻塞添加,直到队列有空位
poll(timeout)	阻塞获取元素,超时返回

当线程池创建的时候,核心线程数是多少?

默认没有核心线程数,当任务提交到线程池的时候,才会创建

线程工厂

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class CustomThreadFactory implements ThreadFactory {
    private final String namePrefix;
    private final AtomicInteger threadCount = new AtomicInteger(1);

    public CustomThreadFactory(String poolName) {
        this.namePrefix = "Pool-" + poolName + "-Thread-";
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r, namePrefix + threadCount.getAndIncrement());
        thread.setUncaughtExceptionHandler((t, e) -> {
            System.err.println("Thread " + t.getName() + " threw exception: " + e.getMessage());
        });
        return thread;
    }
}

拒绝策略

AbortPolicy: 直接抛出异常
DiscardPolicy: 偷偷的拒绝你
DiscardOldestPolicy: 剔除掉旧的任务
CallerRunsPolicy: 任务还给调用线程执行
自定义策略:实现RejectedExecutionHandler接口,自己玩 

执行方法说明

ExecutorService ASYNC_THREAD_POOL = new ThreadPoolExecutor(4, 64,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(1024), new CustomThreadFactory("TEST"),
            new ThreadPoolExecutor.AbortPolicy());



    public void test() {

        // 有返回值
        Future<?> submit = ASYNC_THREAD_POOL.submit(() -> "123");
        try {
            Object o = submit.get(1, TimeUnit.SECONDS);
            log.info("o的值为1");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (TimeoutException e) {
            throw new RuntimeException(e);
        }


        // 判断是否执行完毕,执行完成返回null
        Future<?> submit1 = ASYNC_THREAD_POOL.submit(() -> {
            System.out.println(123);
        });
        try {
            submit1.get();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }


        // 没有任务返回值
        ASYNC_THREAD_POOL.execute(()->{
            System.out.println("123");
        });

        // 所有任务执行完毕才返回
        Collection<A> list = new ArrayList<>();
        list.add( new A());
        try {
            ASYNC_THREAD_POOL.invokeAll(list);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        // 一个执行就返回
        try {
            ASYNC_THREAD_POOL.invokeAny(list);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }

        // 平滑关闭线程池:停止接收新任务,但会执行完队列中的剩余任务
        ASYNC_THREAD_POOL.shutdown();


        // 检查线程池是否已触发关闭流程(返回 true 不表示线程池已完全终止)
        ASYNC_THREAD_POOL.isShutdown();

       // 立即关闭线程池:尝试中断所有线程,并返回未执行的任务列表
        ASYNC_THREAD_POOL.shutdownNow();


        // 检查线程池是否完全终止(所有任务完成且线程回收)
        ASYNC_THREAD_POOL.isTerminated();

        try {
            // Blocks until all tasks have completed execution after a shutdown request
            // 阻塞等待线程池终止,超时后返回当前状态
            ASYNC_THREAD_POOL.awaitTermination(1,TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }
    class A implements Callable<String> {
        @Override
        public String call() throws Exception {
            return "中国加油";
        }
    }

spring中使用方法

@Configuration
@EnableAsync
@Slf4j
public class ExecutorConfig {

    @Value("${thread.core_pool_size:8}")
    private int corePoolSize;
    @Value("${thread.max_pool_size:32}")
    private int maxPoolSize;
    @Value("${thread.queue_capacity:128}")
    private int queueCapacity;
    @Value("${thread.keep_alive_seconds:300}")
    private int keepAliveSeconds;

    @Bean(name = "asyncServiceExecutor")
    public Executor asyncServiceExecutor() {
        log.info("**********start asyncServiceExecutor**********");
        ThreadPoolTaskExecutor executor = new CustomerThreadPoolTaskExecutor();
        // 核心线程数
        executor.setCorePoolSize(corePoolSize);
        // 最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        // 缓冲队列
        executor.setQueueCapacity(queueCapacity);
        // 名称前缀
        executor.setThreadNamePrefix("asyncServiceExecutor-");
        // 空闲时间
        executor.setKeepAliveSeconds(keepAliveSeconds);
        // rejection-policy
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化
        executor.initialize();
        log.info("**********start asyncServiceExecutor success**********");
        return executor;
    }
}

@Slf4j
public class CustomerThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {

    private void showThreadPoolInfo(String prefix) {
        ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor();

        if (null == threadPoolExecutor) {
            return;
        }

        log.info("{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize [{}]",
            this.getThreadNamePrefix(), prefix, threadPoolExecutor.getTaskCount(),
            threadPoolExecutor.getCompletedTaskCount(), threadPoolExecutor.getActiveCount(),
            threadPoolExecutor.getQueue().size());
    }

    @Override
    public void execute(Runnable task) {
        showThreadPoolInfo("do execute");
        super.execute(task);
    }

    @Override
    public void execute(Runnable task, long startTimeout) {
        showThreadPoolInfo("do execute");
        super.execute(task, startTimeout);
    }

    @Override
    public Future<?> submit(Runnable task) {
        showThreadPoolInfo("do submit");
        return super.submit(task);
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        showThreadPoolInfo("do submit");
        return super.submit(task);
    }

    @Override
    public ListenableFuture<?> submitListenable(Runnable task) {
        showThreadPoolInfo("do submitListenable");
        return super.submitListenable(task);
    }

    @Override
    public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
        showThreadPoolInfo("do submitListenable");
        return super.submitListenable(task);
    }
}

   @Autowired
    @Qualifier("asyncServiceExecutor")
    private Executor executor;
	
	
	executor.submit (() - >{
	});