线程和数据库连接这些资源都是非常宝贵的资源。那么每次需要的时候创建,不需要的时候销 毁,是非常浪费资源的。那么我们就可以使用缓存的策略,也就是使用线程池。
newCachedThreadPool
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行
很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造
的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并
从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源
newFixedThreadPool
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大
多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,
则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何
线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之
前,池中的线程将一直存在。
newScheduledThreadPool
创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3); scheduledThreadPool.schedule(newRunnable(){
@Override
public void run() {
System.out.println("延迟三秒");
}
}, 3, TimeUnit.SECONDS);
scheduledThreadPool.scheduleAtFixedRate(newRunnable(){ @Override
public void run() {
System.out.println("延迟 1 秒后每三秒执行一次");
}
},1,3,TimeUnit.SECONDS);
newSingleThreadExecutor
Executors.newSingleThreadExecutor()返回一个线程池(这个线程池只有一个线程),这个线程池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行下去。
线程池底层ThreadPoolExecutor
执行器 Executor 是顶级接口,只包含了一个 execute 方法,用来执行一个 Runnable 任务。
执行器服务 ExecutorService 接口继承了 Executor 接口,ExecutorService 是所有线程池的基础接口,它定义了所有线程接口:
线程池执行器 ThreadPoolExecutor 是基础线程池的核心实现,并且可以通过制 ThreadPoolExecutor 的构造参数或者继承 ThreadPoolExecutor,实现自己的线程池。
●
ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor,是能执行周期性任务或定时任务的线程池;
● ForkJoinPool 是 JDK1.7 时添加的类,作为对 Fork/Join 型线程池的实现。
excute
从 Executor 接口继承到的 execute 方法.使用该方法即将一个 Runnable 任务交给线程池去执行。
submit 方法
submit 方法会提交一个任务去给线程池执行,该任务可以是带返回结果的 Callable 任务,也可以是一开始就指定结果的 Runnable 任务,或者不带结果的 Runnable 任务(此时即一开始指定结果为 null)。submit 方法会返回一个与所提交任务相关联的 Future。
● 向线程池提交一个 Runnable 或者 Callable 任务。
● 将 任务 作为参数使用 newTaskFor 方法构造出 FutureTask;
FutureTask 实现了 Runnable 和 Future 两个接口,从而 FutureTask 可以作为 Runnable 交给 Worker(Thread)去运行,也可以作为一个 Future 与任务交互)。
1.线程池使用 execute 方法将 FutureTask 交给当前的 Worker 去运行,并将 FutureTask 以 Future 返回;
然后 Worker 执行任务(即运行 run 方法),在任务完成后,为 Future(FutureTask) 设置结果 —— 设置结果之前,调用 Future 的 get 方法会让调用线程处于阻塞状态:
通过 Future 的 get 方法,获得任务的结果。
invokeAll 方法
invokeAll 方法可以一次执行多个任务,但它并不同等于多次调用 submit 方法。submit 方法是非阻塞的,每次调用 submit 方法提交任务到线程池之后,会立即返回与任务相关联的 Future,然后当前线程继续向后执行。
而 invokeAll 方法是阻塞的,只有当提交的多个任务都执行完毕之后,invokeAll 方法才会返回,执行结果会以List<Future> 返回,该 List<Future> 中的每个 Future 是和提交任务时的 Collection<Callable> 中的任务 Callable 一 一对应的。带 timeout 参数的 invokeAll 就是设置一个超时时间,如果超过这个时间 invokeAll 中提交的所有任务还有没全部执行完,那么没有执行完的任务会被取消(中断),之后同样以一个 List<Future> 返回执行的结果。
invokeAny 方法也是阻塞的,与 invokeAll 方法的不同之处在于,当所提交的一组任务中的任何一个任务完成之后,invokeAny 方法便会返回(返回的结果便是那个已经完成的任务的返回值),而其他任务会被取消(中断)。
awaitTermination
awaitTermination 可以用来判断线程池是否已经关闭。调用 awaitTermination 之后,在 timeout 时间内,如果线程池没有关闭,则阻塞当前线程,否则返回 true;当超过 timeout 的时间后,若线程池已经关闭则返回 true,否则返回 false。该方法一般这样使用:
● 任务全部提交完毕之后,我们调用 shutdown 方法向线程池发送关闭的指令;
● 然后我们通过 awaitTermination 来检测到线程池是否已经关闭,可以得知线程池中所有的任务是否已经执行完毕;
● 线程池执行完已经提交的所有任务,并将自己关闭;
● 调用 awaitTermination 方法的线程停止阻塞,并返回 true;