java 线程池(ThreadPool)的应用--ExecutorService(一)

1.概述

  很多时候为了提高效率,会提前将一些没有强关联的任务做好。例如经营一家菜馆,配菜师傅会将菜事先切好并按份分开,而不是在客人下单后才开始配菜。另一个,如果是一家能容下百十号人的菜馆,往往也是需要提前招多个厨师来同时制作不同客户所点的菜的。在java的并行编程中也是如此,为了提高效率也会提前分配好必要的资源例如,提前创建好线程池,如此在使用线程时则无需进行分配的操作。本章所说的的ExecutorService则类似于一家餐厅,其中也有配菜师傅(thread)、厨师(thread),非24小时营业的餐厅则会有关门的时候,则类似于 ExecutirService.shutdown 操作。如果在关门前,有一个菜还没有上,厨师(thread)正在制作,那么即使在shutdown错做后,也应该等待这份菜制作完,并且客户吃完离店才行,这等待的过程在类似于ExecutirService.awaitTermination的操作。

2.对象说明

ExecutorService
  继承自类 Executor ,它内部提供各种方法用于管理线程池。
Executors
  实际上就是 ExecutorService 接口的实现类。只不过其以工厂模式来提供。
Future
  用于跟踪一个或多个异步task的状态,例如查询task是否运行完,阻塞等待该task运行完成。

3.基本使用

  下面是一个简单的应用示例。其功能则是使用 ExecutorService 管理的线程池来运行两个任务,在两个任务中只是执行简单的打印操作,然后在延迟一段时间后退出。主线程则会等在ExecutorService内部的任务完成,然后进行善后操作。下面是代码

3.1 创建线程池

private static final int POOL_MAX = 20;
ExecutorService mService = Executors.newFixedThreadPool(POOL_MAX,(Runnable r)->{
    return new Thread(r);
});

  使用Executors来创建ExecutorService的一个实例,预申请的线程数量为POOL_MAX。
  工厂类允许自定义工厂类,这里也只是简单的创建一个Thread并返回。

3.2 提交任务

  

Future<?> tracker1 =  mService.submit​(()->{
    myLog("Thread (id:"+Thread.currentThread().getId()+") is running");
    sleepMs(1000);
});

Future<?> tracker2 = mService.submit​(()->{
    myLog("Thread (id:"+Thread.currentThread().getId()+") is running");
    sleepMs(2000);
});

  使用ExecutorService的接口 submit​ 来提交任务,此处两个任务并不会超出线程池的预定制的数量,所以是并行的。submit​的注意事项如下
  a)Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
  b)Invocation has no additional effect if already shut down.
  c)This method does not wait for previously submitted tasks to complete execution.
  提交一个任务,也会返回一个类 Future 的实例,用于跟踪该 task。

3.3 等待任务执行完成

  前面说过,Future的实例用于跟踪提交的task,下面get接口则用于获取被跟踪task的状态。

myLog("waiting task1 to be done.");
tracker1.get();
myLog("waiting task2 to be done.");
tracker2.get();

  get会等到前面提交的任务主动退出,如果提交的任务中存在死循环,那么主线程就永远等在这了。

3.4 关闭线程池

/* Attempts to stop all actively executing tasks  */
mService.shutdown();
/* waiting all of thread in the pool is done during 10 second */
mService.awaitTermination(10000,TimeUnit.MICROSECONDS);

  关闭线程池意味着在其所在程序的生命周期中不再别使用了。shutdown会停止本线程值接收任何新任务了,即无法通过submit等接口提交新任务,但不会影响在该接口调用前所提交的task。
  awaitTermination则用在shutdown之后调用,调用者会在超时时间内等待调用shutdown之前的任务完成并退出。返回false代表超时返回,true代表线程池中所有任务都完成,并主动返回。

3.5 执行结果

flagstaff@flagstaff-pc:~/work/test/java/ExecutorService$ javac -d . ExecutorServiceTest.java
flagstaff@flagstaff-pc:~/work/test/java/ExecutorService$ java -cp . ExecutorServiceTest
[2022-06-06T08:35:53.213Z] Thread (id:10) is running
[2022-06-06T08:35:53.213Z] waiting task1 to be done.
[2022-06-06T08:35:53.213Z] Thread (id:9) is running
[2022-06-06T08:35:54.232Z] waiting task2 to be done.
[2022-06-06T08:35:55.232Z] all of tasks are done

4. 完整源码

ExecutorService

https://gitee.com/solo-king/javaTestAbout/tree/master/ExecutorService
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值