线程池的理解

Posted Java引导者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池的理解相关的知识,希望对你有一定的参考价值。


 一

什么是线程池

线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程。线程池中线程的数量通常完全取决于可用内存数量和应用程序的需求。然而,增加可用线程数量是可能的。线程池中的每个线程都有被分配一个任务,一旦任务已经完成了,线程回到池子中并等待下一次分配任务。

 二
线程池的处理过程

创建线程池需要使用ThreadpoolExeuctor 类:
public ThreadPoolExecutor(int corePoolSize,    //核心线程的数量
                         int maximumPoolSize,    //最大线程数量
                         long keepAliveTime,    //超出核心线程数量以外的线程空余存活时间
                         TimeUnit unit,    //存活时间的单位
                         BlockingQueue<Runnable> workQueue,    //保存待执行任务的队列
                         ThreadFactory threadFactory,    //创建新线程使用的工厂
                         RejectedExecutionHandler handler // 当任务无法执行时的处理器
                         )
{...}

线程池具体的执行方法:

public void execute(Runnable command) {
   if (command == null)
       throw new NullPointerException();

   int c = ctl.get();
   //1.当前池中线程比核心数少,新建一个线程执行任务
   if (workerCountOf(c) < corePoolSize) {  
       if (addWorker(command, true))
           return;
       c = ctl.get();
   }
   //2.核心池已满,但任务队列未满,添加到队列中
   if (isRunning(c) && workQueue.offer(command)) {  
       int recheck = ctl.get();
       if (! isRunning(recheck) && remove(command))    //如果这时被关闭了,拒绝任务
           reject(command);
       else if (workerCountOf(recheck) == 0)    //如果之前的线程已被销毁完,新建一个线程
           addWorker(null, false);
   }
   //3.核心池已满,队列已满,试着创建一个新线程
   else if (!addWorker(command, false))
       reject(command);    //如果创建新线程失败了,说明线程池被关闭或者线程池完全满了,拒绝任务
}

 三
自己创建一个线程池


1.先定义线程池的几个关键属性的值:

private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2; // 核心线程数为 CPU 数*2
private static final int MAXIMUM_POOL_SIZE = 64;    // 线程池最大线程数
private static final int KEEP_ALIVE_TIME = 1;    // 保持存活时间 1秒
  • 设置核心池的数量为 CPU 数的两倍,一般是 4、8,好点的 16个线程

  • 最大线程数设置为 64

  • 空闲线程的存活时间设置为 1 秒


2.然后根据处理的任务类型选择不同的阻塞队列

如果是要求高吞吐量的,可以使用 SynchronousQueue 队列;如果对执行顺序有要求,可以使用 PriorityBlockingQueue;如果最大积攒的待做任务有上限,可以使用 LinkedBlockingQueue。

private final BlockingQueue<Runnable> mWorkQueue = new LinkedBlockingQueue<>(128);


3.然后创建自己的 ThreadFactory

在其中为每个线程设置个名称:

private final ThreadFactory DEFAULT_THREAD_FACTORY = new ThreadFactory() {
   private final AtomicInteger mCount = new AtomicInteger(1);

   public Thread newThread(Runnable r) {
       Thread thread = new Thread(r, TAG + " #" + mCount.getAndIncrement());
       thread.setPriority(Thread.NORM_PRIORITY);
       return thread;
   }
};


4.然后就可以创建线程池了

private ThreadPoolExecutor mExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME,
       TimeUnit.SECONDS, mWorkQueue, DEFAULT_THREAD_FACTORY,
       new ThreadPoolExecutor.DiscardOldestPolicy());

 四

总结

线程池在项目开发中基本都会用到的,希望小伙伴们能好好的学习学习,文章里面还涉及到了一些队列的知识下一个文章会给他家讲解一下队列有关的知识。


以上是关于线程池的理解的主要内容,如果未能解决你的问题,请参考以下文章

记录一次线程池的在项目中的实际应用,讲解一下线程池的配置和参数理解。

IDEA对新建java线程池的建议

newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段

线程池的使用场景和代码实现!

线程池的理解

线程池的理解及使用