搜文章
推荐 原创 视频 Java开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发
Lambda在线 > Java引导者 > 线程池的理解

线程池的理解

Java引导者 2018-06-28


 一

什么是线程池

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

 二
线程池的处理过程

创建线程池需要使用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());

 四

总结

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


版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《线程池的理解》的版权归原作者「Java资源社区」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注Java资源社区微信公众号

Java资源社区微信公众号:JavaZiYuanSheQu

Java资源社区

手机扫描上方二维码即可关注Java资源社区微信公众号

Java资源社区最新文章

精品公众号随机推荐