过多的短暂线程是开销极大的,所以用线程池吧,每个线程结束后,不会立马消亡,而是入池等待下一个服务
想要停止一个线程需要两步,一步是知道哪个线程去处理,一步是线程本身要有停止的能力
Callables and Futures
Callable
就是 Runnable
的升级版,是一个泛型,接受返回类型,执行后也会有个返回值。但是直接获取这个返回值 Callable
是做不到的,所以要用 Future
包一下,通过 Future
来获取
Callable<Integer> task = . . .;
var futureTask = new FutureTask<Integer>(task);
var t = new Thread(futureTask); // it's a Runnable t.start(); . . .
Integer result = futureTask.get(); // it's a Future
FutureTask
实现了 Future
和 Runnable
,所以满足 “is-a” 条件
可能是历史遗留因素,Thread
只接受 Runnable
,所以需要 Future
包一下
带参数的 Runnable
可以让 Runnable 包含几个成员变量作为参数
暂时不理解为什么不能用 BiConsumer
Executors (Thread Pools)
三个 factory methods,来产生缓存式,定长式,单线式的池。其中单线的用来测试性能,可以比较使用并发到底性能有没有改变 (想想也是,一旦并发就会有阻塞,有时候反而会更慢)
submit
在使用上,前面的可以忘记掉,submit
任何 able,然后返回一个 Future
Future<T> submit(Callable<T> task)
Future<?> submit(Runnable task)
Future<T> submit(Runnable task, T result)
shut down
shutdown
会停止接受新的 task,然后在 task 都完成后,关掉线程池
shutdownNow
在此基础上,停止尚未开始的 task,然后完成之后关掉
scheduled
除了立马执行的普通线程池,还有类似的定时线程和线程池
Controlling Groups of Tasks
总的来说,线程池的使用流程为:
- 工厂方法创建线程池
- 给
submit
Callable
或者Runnable
给线程池,并接受好Future
- 等待
Future
返回值 - 关闭线程池