有界、无界队列对ThreadPoolExcutor执行的影响

来源:互联网 发布:sql 存储过程输出 编辑:程序博客网 时间:2024/06/10 21:14
ava提供了4钟线程池:
newCachedThreadPool
newFixedThreadPool
newSingleThreadExecutor
newScheduledThreadPool


查看源码会发现,这四种线程池都直接或者间接获取的ThreadPoolExecutor实例 ,只是实例化时传递的参数不一样。所以如果java提供的四种线程池满足不了我们的需求,我们可以创建自定义线程池。
ThreadPoolExecutor的构造方法如下:




其中:
corePoolSize: 核心池的大小。 当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中
maximumPoolSize: 线程池最大线程数,它表示在线程池中最多能创建多少个线程;
keepAliveTime: 表示线程没有任务执行时最多保持多久时间会终止。
unit: 参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:
[plain] view plain copy print?
TimeUnit.DAYS;               //天  
TimeUnit.HOURS;             //小时  
TimeUnit.MINUTES;           //分钟  
TimeUnit.SECONDS;           //秒  
TimeUnit.MILLISECONDS;      //毫秒  
TimeUnit.MICROSECONDS;      //微妙  
TimeUnit.NANOSECONDS;       //纳秒  
workQueue: 一个阻塞队列,用来存储等待执行的任务。 一般来说,这里的阻塞队列有以下几种选择:
[plain] view plain copy print?
<span style="font-size:14px;">ArrayBlockingQueue;  
LinkedBlockingQueue;  
SynchronousQueue;</span>  
threadFactory: 线程工厂,主要用来创建线程;
handler: 表示当拒绝处理任务时的策略,有以下四种取值:
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:只要线程池不关闭,该策略直接在调用者线程中,运行当前被丢弃的任务
个人认为这4中策略不友好,最好自己定义拒绝策略,实现RejectedExecutionHandler接口


以下主要讲解存储等待执行的任务的队列对线程池执行的影响。
一.有界队列
1.初始的poolSize < corePoolSize,提交的runnable任务,会直接做为new一个Thread的参数,立马执行 。
2.当提交的任务数超过了corePoolSize,会将当前的runable提交到一个block queue中,。
3.有界队列满了之后,如果poolSize < maximumPoolsize时,会尝试new 一个Thread的进行救急处理,立马执行对应的runnable任务。
4.如果3中也无法处理了,就会走到第四步执行reject操作。
[java] view plain copy print?
public class ThreadPoolExcutorTest implements Runnable {  
      
      
    public String name;  
      
    public ThreadPoolExcutorTest(String name) {  
        this.name = name;  
    }  
      
    @Override  
    public void run() {  
        System.out.println(name);  
        try {  
            Thread.sleep(1000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
          
    }  
      
    public static void main(String[] args) {  
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(3);  
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(  
                            1, //corePoolSize  
                            2,  //maximumPoolSize  
                            1L,  
                            TimeUnit.SECONDS,  
                            workQueue  
                            );  
        threadPool.execute(new ThreadPoolExcutorTest("任务1"));  
        threadPool.execute(new ThreadPoolExcutorTest("任务2"));  
        threadPool.execute(new ThreadPoolExcutorTest("任务3"));  
        threadPool.execute(new ThreadPoolExcutorTest("任务4"));  
        threadPool.execute(new ThreadPoolExcutorTest("任务5"));  
        threadPool.execute(new ThreadPoolExcutorTest("任务6"));  
        threadPool.shutdown();  
          
    }  
  
  
}  


执行结果是:


且线程是两个两个执行的。
分析:线程池的corePoolSize为1,任务1提交后,线程开始执行,corePoolSize 数量用完,接着任务2、3、4提交,放到了有界队列中,此时有界队列也满了。继续提交任务5,由于当前运行的线程数poolSize < maximumPoolsize,线程池尝试new一个新的线程来执行任务5,所以任务5会接着执行。当继续提交任务6,时,poolSize达到了maximumPoolSize,有界队列也满了,所以线程池执行了拒绝操作。
二.无界队列
与有界队列相比,除非系统资源耗尽,否则无界的任务队列不存在任务入队失败的情况。当有新的任务到来,系统的线程数小于corePoolSize时,则新建线程执行任务。当达到corePoolSize后,就不会继续增加,若后续仍有新的任务加入,而没有空闲的线程资源,则任务直接进入队列等待。若任务创建和处理的速度差异很大,无界队列会保持快速增长,直到耗尽系统内存。


[java] view plain copy print?
public class ThreadPoolExcutorTest2 implements Runnable {  
  
    public Integer count;  
      
    public ThreadPoolExcutorTest2(Integer count) {  
        this.count = count;  
    }  
      
    @Override  
    public void run() {  
        System.out.println("任务" + count);  
        try {  
            Thread.sleep(2000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
    }  
      
    public static void main(String[] args) throws InterruptedException {  
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();  
          
        ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 1L, TimeUnit.SECONDS, workQueue);  
        for (int i = 1; i <= 20; i++) {  
            pool.execute(new ThreadPoolExcutorTest2(i));  
        }  
        Thread.sleep(1000);  
        System.out.println("线程池中队列中的线程数量:" + workQueue.size());  
          
          
        pool.shutdown();  
    }  
}  


执行结果为:


如果修改了线程池的maximumPoolSize参数(大于corePoolSize的大小),程序执行结果不受影响。所以对于有界队列,maximumPoolSize的设置设置的再大对于线程的执行是没有影响的。
总结:
可以用以下一句总结:
当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略。
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 儿童保暖雨靴 女式雨鞋雨靴 女士雨鞋雨靴时尚 雨鞋 雨靴 女 时尚 儿童雨鞋雨靴 雨靴什么牌子好 儿童雨靴批发 儿童雨靴哪个牌子好 儿童雨鞋雨靴女 国内雨靴品牌 雨靴哪里有卖 上海回力雨靴 哪个牌子的雨靴好 高筒雨靴价格 一双雨靴多少钱 雨鞋男 雨鞋图片 雨鞋拼音 时尚女雨鞋 雨鞋鞋套 硅胶雨鞋 男款雨鞋 雨鞋套价格 穿雨鞋图片 雨鞋淘宝 防雨鞋 雨鞋雨鞋 儿童雨鞋 雨鞋的拼音 买雨鞋 棉雨鞋 绝缘雨鞋 广东雨鞋厂 大人雨鞋 雨鞋儿童女 男生雨鞋 雨鞋 时尚 雨鞋女款 雨鞋生产厂家 女士漂亮的雨鞋 小孩雨衣雨鞋