线程池的学习

Posted IT小白架构师之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池的学习相关的知识,希望对你有一定的参考价值。


第一节

前言

       hello大家好,断更的小编再次出现,不能够做到每天一更,请大家见谅,毕竟咱们还是个打工人,所谓:打工人、打工魂、打工都是人上人。不干活哪来饭吃?



        今天我们来一起学习下线程池,那么创建线程的集中方式大家还记得吗?

   



继承Thread类




实现Runnable接口




实现Callable接口(可有返回值)


        在项目迭代开发的过程中,多线程开发为了快速高效的解决业务需求,大多使用创建线程的方式去异步执行,创建线程固然方便,但是不规范的创建线程,可能会导致资源浪费或者资源超出主机上线,导致服务器宕机的情况。线程池的出现解决了这个问题,使用线程池可以带来几个好处:




  • 第一:降低资源消耗。通过重复利用已经创建的线程,来降低线程创建和销毁释放造成的消耗时间和资源。


  • 第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行,可以使用线程池闲置的线程直接执行


  • 第三:提高线程的管理性。线程是重要的资源之一,如果每次需要线程处理就无节制地创建,不仅会消耗系统资源,还会降低系统的响应时长及稳定性,使用线程池可以进行统一的创建、分配、调优和监控。



    JDK中提供了线程池创建的API,我们可以使用JDK自带线程池类创建并管理线程池。


第二节

线程池的参数介绍

   

        JDK中提供了java.util.concurrent包,其中创建线程池的使用ThreadPoolExecutor类,查看此类的父类和父类的实现接口如下

线程池的学习

  线程池参数


查看源码的构造方法如下,初始化对象的时候,构造方法需要传入几个参数

 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }


1

线程池创建的几个参数


  • corePoolSize,线程池中保持的线程数量

  • maximumPoolSize,最大线程数,不能超过此线程数量

  • keepAliveTime,当超过核心线程数时,闲置的线程的最大空闲时间

  • unit线程池使用的时间单位

  • workQueue,阻塞队列,当线程数超过核心线程数时,用于保存执行任务的队列,队列的选择有多种

  • threadFactory,线程创建接口,不传递时默认使用,Executors.defaultThreadFactory()

  • RejectedExecutionHandler,拒绝策略




  阻塞队列


        当线程数量超过核心线程数时,无法执行新的线程,则需要将不能执行的任务放置到阻塞队列中,当线程池有闲置对象时,从阻塞队列中取阻塞的线程,进行继续执行。线程创建的阻塞队列对象,传递的接口类型为为BlockingQueue,查看实现类,有6个实现。


线程池的学习

    



2
阻塞队列BlockingQueue的几个实现类


  • ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。

  • LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。

  • PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。

  • DelayQueue:一个使用优先级队列实现的无界阻塞队列。

  • SynchronousQueue:一个不存储元素的阻塞队列。

  • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。



有界与无界的解释:


线程池的学习

有界队列:队列长度有限,会发生队列满的情况,满了以后无法进行存储新的任务


无界队列:队列长度不做限制,可以任意的添加任务,具体能够存入多少任务,需要看系统资源的大小,如果超过资源的最大受限时,JVM会抛出异常,内存溢出

线程池的学习


公平性与非公平性解释:


线程池的学习

场景举例:食堂开始买饭,还没开始放饭,所有人都在门口等着排队(添加到阻塞队列)


公  平  性:开饭的时候,食堂阿姨说,饭来了,每个人都有,从前到后按顺序领取,这叫公平性


非公平性:开饭的时候,食堂阿姨说,饭来了,每个人都有,谁抢到谁先吃,后抢到的后吃,大家一拥而上开始抢饭吃。

线程池的学习



阻塞队列讲解:


ArrayBlockingQueue(有界、非公平性)

是一个用数组实现的有界的阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序,但是不能保证按照阻塞的先后顺序执行,即默认情况下不保证线程公平的访问队列(非公平性)。公平访问队列:是指阻塞的线程可以按照阻塞的先后顺序访问队列,即先阻塞的线程先访问队列。非公平性访问队列:对先等待的线程是非公平的,当队列可用时,阻塞的线程都可以争夺访问队列的资格,有可能先阻塞的线程最后才访问队列。




LinkedBlockingQueue(有界、公平性)

是一个用链表实现的有界阻塞队列。此队列的默认和最大长度为Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序。




PriorityBlockingQueue(有界、支持自定义排序)

PriorityBlockingQueue是一个支持优先级的无界阻塞队列。默认情况下元素采取自然顺序升序排列。也可以自定义类实现compareTo()方法来指定元素排序规则,或者初始化PriorityBlockingQueue时,指定构造参数Comparator来对元素进行排序。需要注意的是不能保证同优先级元素的顺序。




DelayQueue(无界、支持延迟)

是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。DelayQueue非常有用,可以将DelayQueue运用在以下应用场景。缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。




SynchronousQueue(中转型队列)

是一个不存储元素的阻塞队列。每一个put(存)操作必须等待一个take(取)操作,否则不能继续添加元素。SynchronousQueue可以看成是一个传球手,负责把生产者线程处理的数据直接传递给消费者线程。队列本身并不存储任何元素,非常适合传递性场景。





LinkedTransferQueue

支持tryTransfer和transfer方法,

        1.transfer方法如果当前有消费者正在等待接收元素时,transfer方法可以把生产者传入的元素立刻transfer(传输)给消费者。如果没有消费者在等待接收元素,transfer方法会将元素存放在队列的tail节点,并等到该元素被消费者消费了才返回。

        2.tryTransfer方法tryTransfer方法是用来试探生产者传入的元素是否能直接传给消费者。如果没有消费者等待接收元素,则返回false。和transfer方法的区别是tryTransfer方法无论消费者是否接收,方法立即返回,而transfer方法是必须等到消费者消费了才返回。




LinkedBlockingDeque

是一个由链表结构组成的双向阻塞队列。所谓双向队列指的是可以从队列的两端插入和移出元素。双向队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。提供了addFirst、addLast、offerFirst、offerLast、peekFirst和peekLast等方法.


  拒绝策略


        拒绝策略是什么?拒绝策略是当线程池超过最大核心线程数,且队列线程数已经满的情况,如果还有任务到来,程序选择直接抛出异常还是选择等待执行,还是选择抛弃部分线程,可由拒绝策略完成。查看JDK提供的拒接策略接口:

RejectedExecutionHandler有以下几个实现类。


线程池的学习


每个拒绝策略有什么不同?


3
拒绝策略
  • AbortPolicy丢弃任务,并抛出 RejectedExecutionException 异常

  • CallerRunsPolicy:该任务被线程池拒绝,由调用 execute方法的线程排队执行该任务,不丢弃任何任务。

  • DiscardOldestPolicy:抛弃队列最前面的任务,然后重新尝试执行任务。

  •   DiscardPolicy:丢弃任务,不过也不抛出异常。


第三节

手动创建一个线程池


        手动创建线程池,使用JDK的ThreadPoolExecutor类,提前创建好一个Runnale类,用来给线程执行。

  代码环节
package com.yang.thread;import java.util.concurrent.*;
/** * @ClassName ThreadTest * @Description 注释 * @Author yangzhenxin * @Date 2020/12/2 20:12 * @Version 1.0 **/public class ThreadTest {
public static void main(String[] args) throws Exception { //核心线程数 int corePoolSize = 5; //最大线程数 int maximumPoolSize = 10; //闲置时长 long keepAliveTime = 30; // 有界队列 BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2); // 放弃拒绝的任务并抛出异常 RejectedExecutionHandler policyHandler = new ThreadPoolExecutor.AbortPolicy(); ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, policyHandler); long start = System.currentTimeMillis(); for (int i = 0; i < 40; i++) { MyTask myTask = new MyTask(); myTask.setNum(String.valueOf(i+1)); threadPool.execute(myTask); System.out.println("核心线程数" + threadPool.getCorePoolSize()); System.out.println("最大线程数" + threadPool.getMaximumPoolSize()); System.out.println("线程池数" + threadPool.getPoolSize()); System.out.println("队列任务数" + threadPool.getQueue().size()); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); }
System.out.println(System.currentTimeMillis()-start); System.out.println("-------------"); threadPool.shutdown(); if (threadPool.awaitTermination(6, TimeUnit.SECONDS)) { threadPool.shutdownNow(); } }}class MyTask implements Runnable { private String num;
public String getNum() { return num; }
public void setNum(String num) { this.num = num; }
@Override public void run() { try { Thread.currentThread().sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ", hello,序号"+num); }

      示例代码的拒绝策略使用AbortPolicy(丢弃任务,并抛出 RejectedExecutionException 异常),由于程序生成了40个线程,但是最大线程数为10,序列中只能存放两个任务,故最多可执行12个任务,超出任务范围就抛出异常。但不影响已启动的任务,运行结果如下:

/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/bin/java "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=52020:/Applications/IntelliJ IDEA.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/tools.jar:/Users/yangzhenxin/web/idea-Yang/ThReadStudy/out/production/ThReadStudy com.yang.thread.ThreadTestobjc[3425]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/bin/java (0x10d1e74c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10e2104e0). One of the two will be used. Which one is undefined.核心线程数5最大线程数10线程池数1队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数2队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数3队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数4队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数5队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数5队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数5队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数6队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数7队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数8队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数9队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.yang.thread.MyTask@4dc63996 rejected from java.util.concurrent.ThreadPoolExecutor@d716361[Running, pool size = 10, active threads = 10, queued tasks = 2, completed tasks = 0] at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047) at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369) at com.yang.thread.ThreadTest.main(ThreadTest.java:29)pool-1-thread-1, hello,序号1pool-1-thread-4, hello,序号4pool-1-thread-3, hello,序号3pool-1-thread-2, hello,序号2pool-1-thread-5, hello,序号5pool-1-thread-6, hello,序号8pool-1-thread-7, hello,序号9pool-1-thread-8, hello,序号10pool-1-thread-9, hello,序号11pool-1-thread-10, hello,序号12pool-1-thread-3, hello,序号7pool-1-thread-1, hello,序号6


使用CallerRunsPolicy(不丢弃任务)结果如下,必须排队将程序处理完毕才结束,当队列消耗完成后,继续往队列添加任务,保证所有线程都能执行

/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/bin/java "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=52859:/Applications/IntelliJ IDEA.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/lib/tools.jar:/Users/yangzhenxin/web/idea-Yang/ThReadStudy/out/production/ThReadStudy com.yang.thread.ThreadTestobjc[3527]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/bin/java (0x1044ef4c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x1045774e0). One of the two will be used. Which one is undefined.核心线程数5最大线程数10线程池数1队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数2队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数3队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数4队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数5队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数5队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数5队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数6队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数7队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数8队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数9队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>pool-1-thread-1, hello,序号1pool-1-thread-2, hello,序号2main, hello,序号13核心线程数5最大线程数10pool-1-thread-6, hello,序号8pool-1-thread-9, hello,序号11pool-1-thread-4, hello,序号4pool-1-thread-10, hello,序号12pool-1-thread-3, hello,序号3pool-1-thread-5, hello,序号5pool-1-thread-8, hello,序号10pool-1-thread-7, hello,序号9线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>pool-1-thread-1, hello,序号6pool-1-thread-2, hello,序号7pool-1-thread-6, hello,序号15pool-1-thread-5, hello,序号18pool-1-thread-3, hello,序号17pool-1-thread-4, hello,序号16pool-1-thread-9, hello,序号14pool-1-thread-8, hello,序号19main, hello,序号24核心线程数5pool-1-thread-7, hello,序号20pool-1-thread-10, hello,序号21最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>pool-1-thread-1, hello,序号22pool-1-thread-2, hello,序号23pool-1-thread-7, hello,序号31pool-1-thread-10, hello,序号32pool-1-thread-9, hello,序号29pool-1-thread-5, hello,序号26pool-1-thread-6, hello,序号25pool-1-thread-8, hello,序号30pool-1-thread-3, hello,序号27pool-1-thread-4, hello,序号28main, hello,序号35核心线程数5最大线程数10线程池数10队列任务数0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>核心线程数5最大线程数10线程池数10队列任务数1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>15020-------------pool-1-thread-1, hello,序号33pool-1-thread-2, hello,序号34pool-1-thread-6, hello,序号40pool-1-thread-7, hello,序号36pool-1-thread-10, hello,序号37pool-1-thread-9, hello,序号38pool-1-thread-5, hello,序号39
Process finished with exit code 0

其他策略可自行尝试

  问题拓展


问题拓展:线程的submit和execute方法的区别是什么?

submit

线程池的学习

execute



线程池提供了submit和execute两种方式来执行线程任务,通过上面的源码可以看到,

  1. submit有三个构造方法,可以执行实现Runnable接口的线程,也可以执行实现Callable接口的线程。execute只能执行实现Runnable接口的线程。

  2. submit方法有返回值,但是execute没有

  3. submit支持异常捕获,意思就是如果你在你的task里会抛出checked或者unchecked exception,而你又希望外面的调用者能够感知这些exception并做出及时的处理,那么就需要用到submit,通过捕获Future.get抛出的异常。future是submit的返回值。



扫描二维码

关注我吧

IT小白架构师之路



以上是关于线程池的学习的主要内容,如果未能解决你的问题,请参考以下文章

Java线程池详解

C++学习记录:一个小线程池的源码分析

C++学习记录:一个小线程池的源码分析

C++学习记录:一个小线程池的源码分析

Java-----关于线程池的使用

线程池的学习