好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

源码分析Java中ThreadPoolExecutor的底层原理

一、根据代码查看jdk提供的3种线程池创建

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

public class TestController {

     public static void main(String[] args) {

         ExecutorService executorService = Executors.newCachedThreadPool(); //快

         ExecutorService executorService1 = Executors.newFixedThreadPool( 10 ); //慢

         ExecutorService executorService2 = Executors.newSingleThreadExecutor(); //很慢

 

         for ( int i = 0 ; i < 100 ; i++) {

             executorService.execute( new MyTask(i));

         }

     }

}

 

class MyTask implements Runnable{

     private int i;

 

     public MyTask( int i) {

         this .i = i;

     }

 

     @Override

     public void run() {

         System.out.println(Thread.currentThread()+ "-" +i);

         try {

             Thread.sleep( 1000 );

         } catch (InterruptedException e) {

             e.printStackTrace();

         }

     }

}

在运行过程中可以发现3者速度有所差别,当然3者的速度要根据实际处理自行判别,此处只以此代码业务为例。

二、3种方式源码分析

1、Executors.newCachedThreadPool()

源码参数为:

0, 
Integer.MAX_VALUE,
60L, 
TimeUnit.SECONDS,
new SynchronousQueue<Runnable>()

以下图中的外包公司为例(结合图观看),corePoolSize为0,即核心员工数为0;maximumPoolSize为Integer.MAX_VALUE,即非核心员工数为2的31次方-1;且BlockingQueue为同步队列。当任务进来后分配给队列,通过队列分配给非核心员工,下一个任务再进入队列,以此循环执行,直到任务执行完成或者非核心员工都没有空闲时,执行拒绝策略。

2、Executors.newFixedThreadPool(10)

源码参数为:

nThreads, 
nThreads,
0L, 
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()

以下图中的外包公司为例(结合图观看),corePoolSize为10,即核心员工数为10;maximumPoolSize为10,即无非核心员工,且BlockingQueue为链表队列,链表队列最大数为2的31次方-1,若到达最大值后执行拒绝策略。当任务进来后分配10个任务给10个核心员工,其余任务进入链表队列,当核心员工有空闲时将链表队列中的某任务给与空闲员工。以此循环执行。

3、Executors.newSingleThreadExecutor()

源码参数为:

1, 
1,
0L, 
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()

以下图中的外包公司为例(结合图观看),corePoolSize为1,即核心员工数为1;maximumPoolSize为1,即无非核心员工,且BlockingQueue为链表队列,链表队列最大数为2的31次方-1,若到达最大值后执行拒绝策略。当任务进来后分配1个任务给1个核心员工,其余任务进入链表队列,当核心员工有空闲时将链表队列中的某任务给与空闲员工。以此循环执行。

三、自定义方式执行

?

1

2

3

4

5

6

7

8

9

10

11

12

13

     public class TestController {

     public static void main(String[] args) {

         ExecutorService executorService = Executors.newCachedThreadPool(); //快

         ExecutorService executorService1 = Executors.newFixedThreadPool( 10 ); //慢

         ExecutorService executorService2 = Executors.newSingleThreadExecutor(); //很慢

         ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 10 , 20 ,

                                 0L, TimeUnit.MILLISECONDS,

                                             new ArrayBlockingQueue<Runnable>( 10 ));

         for ( int i = 0 ; i < 100 ; i++) {

             threadPoolExecutor.execute( new MyTask(i));

         }

     }

}

运行结果如图:

当线程执行到任务30时将会报出异常,为什么下面还会继续执行任务11-20呢?

其实这与提交优先级、执行优先级有关

提交优先级

在执行任务1-10是会将任务直接给核心员工,当任务11-20进来后会分配到队列等待,此时任务21-30进来后发现队列与核心员工中都存在任务,会将其分配给非核心员工执行。当40以后的任务进来后,由于没有空闲人员,将会抛出异常。

执行优先级

在执行任务1-10是会将任务直接给核心员工,任务11-20进来后会分配给非核心员工执行,当任务21-30进来后会分配到队列等待。当40以后的任务进来后,由于没有空闲人员,将会抛出异常。

以上就是源码分析Java中ThreadPoolExecutor的底层原理的详细内容,更多关于Java ThreadPoolExecutor的资料请关注其它相关文章!

原文链接:https://juejin.cn/post/7229898205257171005

查看更多关于源码分析Java中ThreadPoolExecutor的底层原理的详细内容...

  阅读:13次