线程池

本文纯属个人理解,如有正确,纯属巧合

来源:Java并发编程的艺术

线程池原理:提交任务后,如果发现当前“已经new的线程”小于corePool,即使有空闲的线程存在,也new个新的线程执行该任务。否则,将其加入BlockingQueue队列中,等待已有的线程“循环”去执行队列中的任务,如果此时队列也满了,则需要再次判断当前“已经new的线程”是否小于maximumPoolSize,如果小于,则新建线程;否则,根据拒绝策略进行处理。框架更倾向使用队列,因为创建新线程需要获取全局锁。

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

AbortPolicy:直接抛出异常。
CallerRunsPolicy:只用调用者所在线程来运行任务,比如main线程。
DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
DiscardPolicy:不处理,丢弃掉。

prestartAllCoreThreads():线程池提前创建并启动所有基本线程

ArrayBlockingQueue(int capacity):是一个基于数组结构的【有界】阻塞队列,此队列FIFO原则对元素进行排序

   //keepAliveTime这个时间是maximumPoolSize-corePoolSize以外的空闲线程存活时间!!
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通常高于ArrayBlocingQueue.静态工厂Executors.newFixedThreadPool()使用这个队列。

    //corePoolSize==maximumPoolSize;keepAliveTime=0
    //最大线程数=nThreads+linkedblockingqueu.size
    //无界队列。先创建nThreads个线程,其他未执行的线程放到队列中
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    //corePoolSize==maximumPoolSize==1
    //单线程执行,保证线程的顺序执行
    public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }

SynchronousQueue:一个【不存储元素的阻塞队列】。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常高于Linkedblockingqueue,静态工厂方法Executors.newCachedThreadPool()使用这个队列。

注意:在使用SynchronousQueue通常要求maximumPoolSize是无界的,这样就可以避免上述情况发生(如果希望限制就直接使用有界队列)。对于使用SynchronousQueue的作用jdk中写的很清楚:此策略可以避免在处理可能具有内部依赖性的请求集时出现锁。

什么意思?如果你的任务A1,A2有内部关联,A1需要先运行,那么先提交A1,再提交A2,当使用SynchronousQueue我们可以保证,A1必定先被执行,在A1么有被执行前,A2不可能添加入queue中。

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

创建ForkJoin框架中用到的ForkJoinPool线程池,一个拥有多个任务队列(以便减少连接数),它默认使用当前机器可用的CPU个数作为并行数。

    /**
     * Creates a work-stealing thread pool using all
     * {@link Runtime#availableProcessors available processors}
     * as its target parallelism level.
     * @return the newly created thread pool
     * @see #newWorkStealingPool(int)
     * @since 1.8
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

PriorityBlockingQueue:一个具有优先级的【无限】阻塞队列。

shutdown():用于关闭启动线程,如果不调用该语句,jvm不会关闭。
awaitTermination():用于等待子线程结束,再继续执行下面的代码。该例中我设置一直等着子线程结束。先shutdown,再awaitTermination()

参考:Java线程池使用说明
参考:awaitTermination() shutdown()
参考:《Java并发编程的艺术》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值