博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程池-自定义线程池
阅读量:5149 次
发布时间:2019-06-13

本文共 3995 字,大约阅读时间需要 13 分钟。

最近在研究Executors线程池,出了常用的4个基本创建线程池的方法,newFixedThreadPool(),newSingleThreadExextor(),newCachedThreadPool(),newScheduledThreadPool()之外,我们完全可以通过自定义的方式实现自己想要的线程池,进而满足我们项目需求。

对于自定义线程池也是基于ThreadPoolExecutor的构造函数来设置自定义的。先对其构造函数有一个基本了解

/**     *     * @param corePoolSize   池中所保存的核心线程数     * @param maximumPoolSize  池中允许的最大线程数     * @param keepAliveTime   非核心线程空闲等待新任务的最长时间,超过此时间,线程则会被回收     * @param unit  参数时间单位     * @param workQueue   任务队列     */    public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue
workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }

直接通过创建的方式就可以自定义一个我们想要的线程,自定义线程分为两种,种一:有界队列;种二:无界队列,今日我们通过有界队列对自定义线程有一个深入的了解。

何为有界队列?

  • 在使用有界队列时,若有新的任务需要执行,如果线程池实际线程数小于corePoolSize,则优先创建线程,若大于corePoolSize,则会将任务加入队列。若队列已满,则在总线程数不大于maximumPoolSize的前提下,创建新的线程,若线程数大于maximumPoolSize,则执行拒绝策略,或其他自定义方式。

通过创建一个简单的实体类和一个测试方法来实现。

实体类:

public class MyTask  implements Runnable{
private int taskId; private String taskName; //构造函数 public MyTask(int taskId,String taskName){ this.taskId=taskId; this.taskName=taskName; } @Override public void run() { System.out.println("run taskId="+this.taskId); try { //每次调用线程都沉睡5秒 Thread.sleep(5*1000); } catch (InterruptedException e) { e.printStackTrace(); } } public String toString(){ return Integer.toString(this.taskId); }}

测试类:我们通过创建ThreadPoolExecutor来控制线程数,指定想要的队列。

public static void main(String[] args) {        ThreadPoolExecutor pool = new ThreadPoolExecutor(                1,    //coreSize                2,   //MaxSize                60, //60                TimeUnit.SECONDS,                new ArrayBlockingQueue
(3) //指定一种队列(有界队列) ); MyTask mt1 = new MyTask(1, "任务1"); MyTask mt2 = new MyTask(2, "任务2"); MyTask mt3 = new MyTask(3, "任务3"); MyTask mt4 = new MyTask(4, "任务4"); MyTask mt5 = new MyTask(5, "任务5"); MyTask mt6 = new MyTask(6, "任务6"); pool.execute(mt1); pool.execute(mt2); pool.execute(mt3); pool.execute(mt4); pool.execute(mt5); pool.execute(mt6); pool.shutdown(); }

从ThreadPoolExecutor创建的线程条件我们可以得知,我们创建了一个核心线程数,最大线程数为2,非核心线程等待的时间为60秒。

  • 只执行mt1,则符合核心线程数,所以会直接执行。因为设置的等待时间为60秒,意思就是假设执行mt1用了10秒,假如在剩下的50秒钟无任何线程进入,则该线程池直接被回收。若进入则直接执行下一个线程。
  • 执行mt1,mt2则是核心线程和最大线程,则会在执行完mt1之后,大概5秒之后,执行mt2;
  • ArrayBlockingQueue队列是可以容纳3个值的,所以为mt2,mt3,mt4都可以放入队列中,等待执行。执行4个线程中间的时间间隔则为设置的5秒左右。
  • 而mt5则已经超过了队列的容纳范围,所以重新创建一个新的线程,因为如需放入队列中,所以应该是和mt1同步的执行,无需等待。
  • 而mt6则直接拒绝。因为超过了,最大线程和队列存入个数。最后执行的效果如下:
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task 6 rejected from java.util.concurrent.ThreadPoolExecutor@165e6c89[Running, pool size = 2, active threads = 2, queued tasks = 3, completed tasks = 0]    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)    at Thread.Executors.UseThreadPoolExecutor1.main(UseThreadPoolExecutor1.java:42)    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)    at java.lang.reflect.Method.invoke(Method.java:601)    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)run taskId=1run taskId=5run taskId=2run taskId=3run taskId=4

通过错误数字都可以看到问题的所在。对于在项目中的使用情况,需要根绝具体需求而定。通过学习各种线程,线程池,有一个整体的规划,这样在使用时方能想到,熟能生巧。

转载于:https://www.cnblogs.com/huohuoL/p/10545447.html

你可能感兴趣的文章
专为多设备、多分辨率应用而设计
查看>>
51nod 1298 圆与三角形
查看>>
day 7-7 线程池与进程池
查看>>
VALSE2019总结(6)-年度总结-Re-ID
查看>>
luogu_1414 又是毕业季II
查看>>
List
查看>>
图Graph
查看>>
linux文件截取前几行,后几行,中间几行命令
查看>>
iOS 10中如何搭建一个语音转文字框架
查看>>
百度智能手环方案开源(含源码,原理图,APP,通信协议等)
查看>>
设计模式(三十一)------23种设计模式(23):简单工厂模式
查看>>
9.12日学习笔记
查看>>
spring-data-neo4j 4.2.4release文档概要
查看>>
0049-学校的上网费
查看>>
31、求整数范围中1的个数
查看>>
算法第二章上机实践报告
查看>>
.net
查看>>
Zend studio 常用快捷键与技巧
查看>>
iOS基础知识之类别
查看>>
测试人员关注点
查看>>