Java8七种线程池

七种线程池

java通过工具类Executors种各种线程池的工厂方法创建

所有线程池都可使用ExecutorService接口的引用承接(因为是实现的啊)

(1)CachedThreadPool

  • Exectors.newCachedThreadPool
  • 无长度限制,
  • 当新任务加入CachedThreadPool时。如果池内其他线程无空闲就产生新的线程执行任务,如果空闲就使用空闲的线程执行任务
  • 线程空闲超过一定时间(默认60s,可设置)自动从池中删除
  • 可能会造成内存溢出,一般用FixedThreadPool代替

(2)FixedThreadPool

  • Exectors.newFixedThreadPool(线程数量)
  • 固定线程数量
  • 如果加入任务时线程均不空闲,该任务加入等待队列,当有线程空闲时从等待队列弹出,由刚刚空闲出的线程执行
  • 定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()

(3)ScheduledThreadPool

  • Executors.newScheduledThreadPool(线程数),返回ScheduledExecutorService类型
  • 定长
  • 定时及周期性执行任务
  • 它会不断重复执行任务,而不是执行了线程数就停
ScheduledThreadPool实例.scheduleAtFixedRate(
	() -> {
		执行任务
	}, 
	执行第一个任务之前等待的时间, 
	每多少秒启动下一个线程执行此任务, 
	时间单位
);

(4)SingleThreadExecutor

  • Executors.newSingleThreadExecutor()
  • 容量为1,只用一个线程工作
  • 多余的任务放入队列
  • 任务可以按照指定顺序执行(FIFO,LIFO,优先级)

(5)SingleThreadScheduledExecutor

  • 只有一个线程,可以放入多个任务
  • 这一个线程通过调度执行这些任务
    • 调度类似一个CPU调度多线程执行
    • 这也就说明了,当线程中一个任务被阻塞时,整个线程都是被阻塞的
  • 示例代码1
    public class newSingleThreadScheduledExecutor {
    
        private static final ScheduledExecutorService excutor = Executors.newSingleThreadScheduledExecutor();
        
        public static void main(String[] args) {
            Thread thread1 = new Thread(() -> {
                long end = new Date().getTime();
                System.out.println("time wait:" + (end - start) + ",this is 线程1");
            }, "线程1");
     
            Thread thread2 = new Thread(() -> {
                long end = new Date().getTime();
                System.out.println("time wait:" + (end - start) + ",this is 线程2");
            }, "线程2");
    
            excutor.scheduleWithFixedDelay(thread1, 0, 1, TimeUnit.SECONDS);
            excutor.scheduleWithFixedDelay(thread2, 0, 2, TimeUnit.SECONDS);
        }
     
    }
    
    

(6)ForkJoinWorkerThread

  • 任务盗取:其中的每一个线程维护自己的任务队列,当自己的任务队列中的任务执行完,从其他任务队列拿任务继续执行
  • 和普通线程池不同,任务并不是交给线程池中的队列,而是放到线程自己的队列(正如上文WorkStealingPoll中所说的那样)
  • 它采用的是分治法,将大任务分成几个小任务,小任务再划分小任务
  • 示例代码2
    // 计算1加到999999的总和,每100进行分割,让每一百个数同时相加,返回总和
    public class SumTask extends RecursiveTask<Integer> {
    
        private Integer start = 0;
        private Integer end = 0;
    
        public SumTask(int start, int end) {
            this.start = start;
            this.end = end;
        }
    
        @Override
        protected Integer compute() {
    
            if (end - start < 100) {
                //小于100时直接返回结果
                int sumResult = 0;
                for (int i = start; i <= end; i++) {
                    sumResult += i;
                }
                return sumResult;
            } else {
                //大于一百时进行分割
                int middle = (end + start) / 2;
                SumTask leftSum = new SumTask(this.start, middle);
                SumTask rightSum = new SumTask(middle, this.end);
                // 拆分任务
                leftSum.fork();
                rightSum.fork();
    			// 执行左右任务,并返回结果
                return leftSum.join() + rightSum.join();
            }
        }
    
        public static void main(String[] args) {
            SumTask sumTask = new SumTask(1, 999999);
            sumTask.fork();
            // 开始执行
            System.out.print("result:" + sumTask.join());
        }
    } 
    

(7)WorkStealingPool

  • 任务盗取
  • 不是ThreadPoolExecutor的扩展,是新的线程池类ForkJoinPool的扩展
  • 虽然父类ForkJoinWorkerThread也有任务盗取,但是父类名字上强调分治WorkStealingPool从名字上更强调任务盗取,更加专业化
  • 适合使用在很费时的操作上

  1. https://blog.csdn.net/qq_36850813/article/details/95314464 ↩︎

  2. https://www.jianshu.com/p/a152c0a0d2d0 ↩︎

发布了63 篇原创文章 · 获赞 10 · 访问量 7007

猜你喜欢

转载自blog.csdn.net/weixin_43553694/article/details/104501504