java并发编程(线程池)

387 阅读2分钟
线程池类型
  • FixedThreadPool:固定线程数量的线程池
  • ScheduledThreadPool:支持以某种频率执行任务
  • ForkJoinPool:把任务被递归分解成子任务fork,子任务执行完成后将结果合并join
任务队列类型
  • DelayQueue:无界延时队列,只有到了延时时间才会出队
  • ArrayBlockingQueue:有界队列,基于数组实现
  • LinkedBlockingDeque:基于链表实现,可以设置大小,默认是无界队列
  • PriorityBlockingQueue:无界优先级队列,默认数组长度是11,内部采用了大根堆或小根堆的设计
任务拒绝策略

拒绝策略定义在ThreadPoolExecutor的内部类中

  • AbortPolicy:抛出异常
  • CallerRunsPolicy:由当前提交任务的线程执行
  • DiscardPolicy:啥也不干,不抛出异常,也不会执行任何操作
  • DiscardOldestPolicy:丢弃队列中最老的一个,然后将当前任务提交线程池处理
  • SynchronousQueue:队列不存储任务,新来一个任务开启一个线程,直到线程数达到最大后,触发拒绝策略
任务执行顺序

顺序.png

  • 啥时候创建临时线程: 新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程
  • 啥时候拒绝任务: 核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝
如何设置线程数
  • CPU型任务:当前可用的处理器核数 + 1
  • IO 密集型任务:当前可用的处理器核数 * 2
  • 获取处理器核数:Runtime.getRuntime().availableProcessors()
如何关闭线程池
  • shutdown:线程池不再接收新任务,但会执行完目前所有的任务,线程池进入SHUTDOWN状态
  • shutdownNow:线程池会清空任务队列,同时发出中断信号,让正在执行的任务停止,停不停要看任务有没有进行中断处理,线程池进入STOP状态
如何定义线程池
  • 线程池的核心就是阻塞队列,利用阻塞队列来实现线程阻塞等待去获取任务,线程池参数如下:

    public ThreadPoolExecutor(
        int corePoolSize,       // 核心线程数量,一直存在不会被回收的线程
        int maximumPoolSize,    // 最大线程数量,除了核心线程其他是临时线程
        long keepAliveTime,     // 临时线程的存活时间
        TimeUnit unit,          // 时间单位 
        BlockingQueue workQueue,// 任务队列
        RejectedExecutionHandler handler  // 任务处理策略
    )
    
  • 示例

    public static void main(String[] args) {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2, 64, 
            5L, TimeUnit.MINUTES, 
            new LinkedBlockingQueue<>(30), 
            new ThreadPoolExecutor.AbortPolicy() );
    
        Future<?> future = threadPool.submit(() -> {
            return "success";
        });
        try {
            Object taskResult = future.get();
            System.out.println("taskResult: " + taskResult);
        } catch (InterruptedException | ExecutionException e) {
            System.out.println("Task threw exception: " + e.getCause());
        }
    }
    
线程池异常处理
CompletableFuture.supplyAsync(() -> { int a = 10/0; return 666; }, executor)
.exceptionally(ex -> {
     System.out.printf("异常:"+ex.toString());
     return -1;
})
.thenAccept(res -> {
    System.out.printf("返回值:" + res);
});
相关文章

juejin.cn/post/684490…