java线程池(一)

      参考:https://www.cnblogs.com/dolphin0520/p/3932921.html      https://blog.csdn.net/l_kanglin/article/details/57411851线程池ThreadPoolExecutor.继承关系:ThreadPoolExecutor继承自抽象类AbstractExecutorService.    ...
摘要由CSDN通过智能技术生成
      

参考:https://www.cnblogs.com/dolphin0520/p/3932921.html

      https://blog.csdn.net/l_kanglin/article/details/57411851

线程池ThreadPoolExecutor.

继承关系:

ThreadPoolExecutor继承自抽象类AbstractExecutorService.

        AbstractExcutorService实现了ExecutorService接口

        ExecutorService接口继承了Executor接口

 

构造函数:

     public ThreadPoolExecutor(intcorePoolSize,

                              intmaximumPoolSize,

                              longkeepAliveTime,

                              TimeUnit unit,

                             BlockingQueue<Runnable> workQueue,

                              ThreadFactory threadFactory,

                             RejectedExecutionHandler handler) {

        if (corePoolSize < 0 ||

            maximumPoolSize <= 0 ||

            maximumPoolSize < corePoolSize ||

            keepAliveTime < 0)

            thrownew IllegalArgumentException();

        if (workQueue == null || threadFactory == null || handler == null)

            thrownew NullPointerException();

        this.acc = System.getSecurityManager() == null ?

                null :

                AccessController.getContext();

        this.corePoolSize = corePoolSize;

        this.maximumPoolSize = maximumPoolSize;

        this.workQueue = workQueue;

        this.keepAliveTime = unit.toNanos(keepAliveTime);

        this.threadFactory = threadFactory;

        this.handler = handler;

   }

 共有四个构造函数,但是其它三个构造函数都是调用这个构造函数来完成对象的实例化的。

   各参数的意义:

   corePoolSize:表示线程池的大小,一旦创建,它就是这么大。

maximumPoolSize:表示线程池的最大的大小。当任务过多时,可能会创建新的线程来执行任务,但是总的线程池的大小不能超过这个maximumPoolSize,否则就会抛出异常,或者拒绝任务,这个根据拒绝策略来定。

KeepAliveTime:当线程池中线程的数量大于corePoolSize的时候,如果某个线程空闲时间超过keepAliveTime,就会销毁这个线程。

Unit:keppAliveTime的时间单位。

workQueue:任务缓存队列,当线程数量大于等于corePoolSize的时候,新来的任务就会被缓存到workQueue中。

ThreadFactory:用来创建新的线程的线程工厂。

RejectedExecutionHandler :拒绝处理任务的策略。

 

 

 

线程池的五种状态

    // runState is stored in the high-order bits

    privatestaticfinalintRUNNING    =-1 << COUNT_BITS;

    privatestaticfinalintSHUTDOWN  =  0 << COUNT_BITS;

    privatestaticfinalintSTOP      =  1 << COUNT_BITS;

    privatestaticfinalintTIDYING   =  2 << COUNT_BITS;

privatestaticfinalintTERMINATED3 <<COUNT_BITS;

 

  当线程池刚刚创建的时候处于RUNNING状态,当调用shutdown()方法的时候,线程池会处于SHUTDOWN状态,此时线程池不再接收新的任务,但是会继续把正在执行的任务和缓存队列中的任务都执行完了以后再销毁。当调用线程池的shutdownNow()方法的时候,线程池会进行STOP状态,此时线程池不再接收新的任务,并且会尝试去终止正在执行的任务和清空缓存对列。当线程池为空的时候,即线程池中没有执行的线程了的时候。就会进入TIDYING状态。此时线程池就会执行另一个钩子函数terminate(),执行完这个函数,线程池就会从TIDYING状态变为TERMINATED状态。

如下图:

 

线程池原理:

线程池创建之初,会设定corePoolSizemaximumPoolSize。并且不会创建线程,除非通过预创建的方法prestartAllCoreThreads()或者prestartCoreThread()。在没有预创建的情况下,就是来一个任务创建一个线程。当线程数到达corePoolSize的时候,就会把新来的任务放到缓存队列中。当缓存队列满了以后,就会创建新的线程。当线程数到达maximumPoolSize。再有新的任务过来,就会抛出异常,拒绝任务,并关闭线程池。但是已经在缓存队列中的线程和正在执行的线程会执行完。

当线程的数量大于corePoolSize的时候,如果某个线程的空闲时间超过KeepAliveTime,就会被销毁。

 

 

 

使用示例

importjava.util.concurrent.ArrayBlockingQueue;

importjava.util.concurrent.ThreadPoolExecutor;

importjava.util.concurrent.TimeUnit;

 

publicclass TreadPoolTest {

    publicstaticvoid main(String[] args) {

    ThreadPoolExecutor executor=new ThreadPoolExecutor(5,10, 200, TimeUnit.MILLISECONDS, newArrayBlockingQueue<Runnable>(5));

       

    for(inti=0;i<15;i++) {

        MyTaskmyTask=new MyTask(i);

        executor.execute(myTask);

        System.out.println("线程池数目"+executor.getPoolSize()+",队列中正在等待执行的任务数目:"+executor.getQueue().size()+

                   ",已执行完别的任务数目:"+executor.getCompletedTaskCount());

    }

    executor.shutdown();

    }

}

 

class MyTask implements Runnable{

    privateinttaskNum;

    public MyTask(inti) {

        this.taskNum=i;

    }

 

    @Override

    publicvoid run() {

        System.out.println("正在执行task"+taskNum);

         try {

            Thread.currentThread().sleep(4000);

          } catch (Exception e) {

            e.printStackTrace();

         }

         System.out.println("task"+taskNum+"执行完毕");

    }

   

}

 

输出结果:

正在执行task0

线程池数目1,队列中正在等待执行的任务数目:0,已执行完别的任务数目:0

线程池数目2,队列中正在等待执行的任务数目:0,已执行完别的任务数目:0

正在执行task1

线程池数目3,队列中正在等待执行的任务数目:0,已执行完别的任务数目:0

正在执行task2

线程池数目4,队列中正在等待执行的任务数目:0,已执行完别的任务数目:0

正在执行task3

线程池数目5,队列中正在等待执行的任务数目:0,已执行完别的任务数目:0

线程池数目5,队列中正在等待执行的任务数目:1,已执行完别的任务数目:0

正在执行task4

线程池数目5,队列中正在等待执行的任务数目:2,已执行完别的任务数目:0

线程池数目5,队列中正在等待执行的任务数目:3,已执行完别的任务数目:0

线程池数目5,队列中正在等待执行的任务数目:4,已执行完别的任务数目:0

线程池数目5,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

线程池数目6,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

正在执行task10

线程池数目7,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

正在执行task11

线程池数目8,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

正在执行task12

线程池数目9,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

正在执行task13

线程池数目10,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

正在执行task14

task0执行完毕

task1执行完毕

task2执行完毕

正在执行task6

正在执行task5

正在执行task7

task4执行完毕

task3执行完毕

正在执行task9

task10执行完毕

正在执行task8

task14执行完毕

task12执行完毕

task13执行完毕

task11执行完毕

 

从输出结果中可以看出,当缓冲队列满的时候,才会创建新的线程。如果把任务数改为20的时候,输出结果如下:

 

 

正在执行task0

线程池数目1,队列中正在等待执行的任务数目:0,已执行完别的任务数目:0

线程池数目2,队列中正在等待执行的任务数目:0,已执行完别的任务数目:0

线程池数目3,队列中正在等待执行的任务数目:0,已执行完别的任务数目:0

正在执行task1

正在执行task2

线程池数目4,队列中正在等待执行的任务数目:0,已执行完别的任务数目:0

正在执行task3

线程池数目5,队列中正在等待执行的任务数目:0,已执行完别的任务数目:0

线程池数目5,队列中正在等待执行的任务数目:1,已执行完别的任务数目:0

正在执行task4

线程池数目5,队列中正在等待执行的任务数目:2,已执行完别的任务数目:0

线程池数目5,队列中正在等待执行的任务数目:3,已执行完别的任务数目:0

线程池数目5,队列中正在等待执行的任务数目:4,已执行完别的任务数目:0

线程池数目5,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

线程池数目6,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

正在执行task10

线程池数目7,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

正在执行task11

线程池数目8,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

正在执行task12

线程池数目9,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

正在执行task13

线程池数目10,队列中正在等待执行的任务数目:5,已执行完别的任务数目:0

正在执行task14

Exceptionin thread "main" java.util.concurrent.RejectedExecutionException: Task MyTask@7d4991ad rejected fromjava.util.concurrent.ThreadPoolExecutor@28d93b30[Running, pool size = 10,active threads = 10, queued tasks = 5, completed tasks = 0]

    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)

    atjava.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)

    atjava.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)

    at TreadPoolTest.main(TreadPoolTest.java:11)

task4执行完毕

task0执行完毕

task1执行完毕

正在执行task7

task2执行完毕

task11执行完毕

task3执行完毕

正在执行task9

task10执行完毕

正在执行task8

task12执行完毕

正在执行task6

正在执行task5

task13执行完毕

task14执行完毕

 

从上面可以看出,当缓冲队列满的时候,而且线程池中的线程已经为maximumPoolSize的时候,就会报出异常,但是报出异常之后并不会终止线程池中的线程,而是会把正在执行的线程和缓存队列中的线程都执行完了以后,再终止线程池。

 

 


 

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值