Java线程池

1.ForkJoinPool

分解汇总任务,用很少的线程执行很多的任务

继承RecursiveTask类创建有返回值的task,继承RecursiveAction创建无返回值的task,重写compute方法m在compute方法中来对任务进行分片,调用Taskfork方法fork出新的task,将任务分片执行,如下代码,任务被分城8片

public class ForkJoinPoolTests {

    class MyTask extends RecursiveAction {

        int i = 0;

        public MyTask(int i) {
            this.i = i;
        }

        /**
         * 第一次 i -- 10
         * i -- 50 task 2
         * task1 -- i --> 25 task1.1 task1.2   i--> 17 task1.1.1 task1.1.2 task1.2.1 task1.2.2
         * task2 -- i --> 25 task2.1 task2.2   i--> 17 task2.1.1 task2.1.2 task2.2.1 task2.2.2
         * 最终 task1.1.1 task1.1.2 task1.2.1 task1.2.2 task2.1.1 task2.1.2 task2.2.1 task2.2.2
         * 八个task拿到任务
         */
        @Override
        protected void compute() {
            if (i < 20){
                System.out.println("我能执行了");
            }else {
                i = i / 2;
                new MyTask(i).fork().join();
                new MyTask(i).fork().join();
            }
        }
    }

    @Test
    void doTests() throws IOException {
        ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
        forkJoinPool.execute(new MyTask(100));
        System.in.read();
    }

}

最常见的ForkJoinPool应用

  • 线程池的WorkStealingPool
  • stream流式计算中的parallelStream并行流
2.ThreadPoolExecutor
2.1.七个核心参数
  1. corePoolSize核心线程数
  2. maximumPoolSize 最大线程数(核心线程+非核心线程)
  3. keepAliveTime线程存活时间(线程空闲的时间)
  4. unit线程存活时间单位
  5. workQueue任务队列
  6. threadFactory 线程工场类,管理线程创建的工场类,默认使用非守护线程,优先级的修改,线程名字等
  7. handler 拒绝策略(jdk默认提供了四种,可以自定义)

线程进来如果没有空闲的核心线程,并且没有达到设置的最大核心线程数的时候,会创建新的线程.如果达到核心线程的最大数量,会放到任务队列,当任务队列满的时候会创建非核心线程,非核心线程到达最大数量会执行拒绝策略.

2.2.jdk提供的拒绝策略

需要自定义符合业务场景的拒绝策略

  1. Abort 抛出异常
  2. Discard 丢弃任务,并且不抛出异常
  3. CallerRuns 调用者线程处理任务
  4. DiscardOldest 丢掉队列中等待时间最长的任务,将新的任务加入队列
3.Executors提供的线程池
  • Executors.newSingleThreadExecutor()

    核心线程数和最大线程数都是1个,单线程的线程池,队列为LinkedBlockingQueue,存活时间为0,任务结束就创建新的线程

  • Executors.newCachedThreadPool()

    核心线程数为0,非核心线程数为Integer.MaxValue,线程有60秒存活期,如果没有空闲线程,每来一个新任务会创建一个新的非核心线程,任务队列使用SynchronousQueue,如果没有线程处理提交任务的线程会阻塞

    任务量大小不定的情况可以使用cachedThreadPool

  • Executors.newWorkStealingPool()

    每个线程有自己单独的队列,在当前线程队列任务执行完毕,会去取其他线程队列的任务来执行.内部使用ForkJoinPool

  • Executors.newFixedThreadPool(n)

    核心线程数和最大线程数都是n,线程存活时间是0,即任务到来会创建新的线程,如果超过n个任务,会进入任务队列,使用LinkedBlockingQueue

    任务数量波动不大使用FixedThreadPool

  • Executors.newScheduledThreadPool(n)

    定时任务线程池,n为核心线程数,最大线程数为Integer.MaxValue,存活时间为10毫秒,任务队列为DelayedWorkQueue,按任务时间进行执行

线程池数量大小预估,预估后对程序进行压力测试修改最合适的值

Nthread = Ncpu * Ucpu*(1 + W/C)

Ncpu 处理器的核数,Runtime.getRuntime().availableProcessors()获取线程数

Ucpu 期望的CPU利用率

W/C 等待时间与计算时间比例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不想写代码~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值