前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >对java线程池的一些理解和感悟

对java线程池的一些理解和感悟

作者头像
Meet相识
发布2018-09-12 16:26:06
4550
发布2018-09-12 16:26:06
举报
文章被收录于专栏:技术专栏技术专栏

首先附上线程池知识点详解

示例代码

代码语言:javascript
复制
import java.util.Date;
import java.util.concurrent.*;

public class ThreadPoolTest {

    private static LinkedBlockingQueue queue = new LinkedBlockingQueue<Runnable>(4);
    
    private static ExecutorService pool = new ThreadPoolExecutor(4, 4,
            0L, TimeUnit.MILLISECONDS,queue
    );

    public static void main(String[] args) {
//        pool.execute(new aaa(0));
//        pool.execute(new aaa(1));
//        pool.execute(new aaa(2));
//        pool.execute(new aaa(3));
//
//        for(int i =4;i<13;i++){
//            final int num = i+1;
//
//            try {
//                System.out.println("queue.put第"+(i+1)+"个任务"+new Date());
//                queue.put(new aaa(num));
//                System.out.println("after queue.put 队列大小:"+queue.size());
//            } catch (InterruptedException e1) {
//                e1.printStackTrace();
//            }
//        }
        long start = +new Date().getTime();
        System.out.println("开始执行"+start);

        for(int i =0;i<100;i++){
            final int num = i+1;
            try {
                System.out.println("before-execute-阻塞队列大小:"+queue.size());
                System.out.println("before-execute-向线程池放置并execute第"+(i+1)+"个任务"+new Date());
                pool.execute(new Job(num));

            } catch (RejectedExecutionException e) {
               //阻塞队列慢,线程数达到最大线程数以后的默认抛弃策略
               //抛出RejectedExecutionException异常,开发者catch住自行处理,
               //这里catch住以后放入阻塞队列使得主线程阻塞,直到阻塞队列有位置
                System.out.println("-------------"+RejectedExecutionException.class.getName() + new Date());
                try {
                    queue.put(new Job(num));
                    System.out.println("before-put-阻塞队列大小:"+queue.size()+"  "+new Date());
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        }
        pool.shutdown();

        long end = +new Date().getTime();
        System.out.println("执行完毕,执行时间:"+(start-end));
    }

    public static  class  Job implements Runnable {

        int num;
        public Job(int num) {
            this.num = num;
        }

        @Override
        public void run()  {
            System.out.println("任务"+num +"开始执行" + new Date());
            long startTime = new Date().getTime();

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务"+num +"执行完毕"+new Date().getTime());

        }
    }

}

部分执行日志

代码语言:javascript
复制
开始执行1513129646475
before-execute-阻塞队列大小:0
before-execute-向线程池放置并execute第1个任务Wed Dec 13 09:47:26 CST 2017
before-execute-阻塞队列大小:0
before-execute-向线程池放置并execute第2个任务Wed Dec 13 09:47:26 CST 2017
任务1开始执行Wed Dec 13 09:47:26 CST 2017
before-execute-阻塞队列大小:0
before-execute-向线程池放置并execute第3个任务Wed Dec 13 09:47:26 CST 2017
任务2开始执行Wed Dec 13 09:47:26 CST 2017
before-execute-阻塞队列大小:0
before-execute-向线程池放置并execute第4个任务Wed Dec 13 09:47:26 CST 2017
任务3开始执行Wed Dec 13 09:47:26 CST 2017
before-execute-阻塞队列大小:0
before-execute-向线程池放置并execute第5个任务Wed Dec 13 09:47:26 CST 2017
任务4开始执行Wed Dec 13 09:47:26 CST 2017
before-execute-阻塞队列大小:1
before-execute-向线程池放置并execute第6个任务Wed Dec 13 09:47:26 CST 2017
before-execute-阻塞队列大小:2
before-execute-向线程池放置并execute第7个任务Wed Dec 13 09:47:26 CST 2017
before-execute-阻塞队列大小:3
before-execute-向线程池放置并execute第8个任务Wed Dec 13 09:47:26 CST 2017
before-execute-阻塞队列大小:4
before-execute-向线程池放置并execute第9个任务Wed Dec 13 09:47:26 CST 2017
before-execute-阻塞队列大小:4
before-execute-向线程池放置并execute第10个任务Wed Dec 13 09:47:26 CST 2017
任务9开始执行Wed Dec 13 09:47:26 CST 2017
-------------java.util.concurrent.RejectedExecutionExceptionWed Dec 13 09:47:26 CST 2017
任务2执行完毕1513129649502
任务1执行完毕1513129649502

以示例代码为例对线程池执行过程的理解

一共100个线程,核心线程数为4,最大线程数为5,空闲存活时间为0,阻塞队列为 4

  • 1-4个任务到来的时候,都会启用核心线程来执行任务
  • 5-8个任务到来的时候,会进入阻塞队列等待
  • 第9个任务来的时候,核心线程数和阻塞队列都已经达到上限,所以会开启第五个线程执行第9个任务
  • 第10个任务来的时候,线程达到最大上限,阻塞队列慢,抛出RejectedExecutionException
  • 超过核心线程数未到最大线程数的线程(如上例中第5个线程)只是一个临时工,保证不能进入阻塞队列的部分任务可以得到执行,在执行完任务后会根据构造函数配置的空闲存活时间,在指定时间销毁,而核心线程一经创建则不会销毁

总结

如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务; 如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务; 如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理; 如果线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.12.13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 首先附上线程池知识点详解
  • 示例代码
  • 部分执行日志
  • 以示例代码为例对线程池执行过程的理解
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档