使用Executor

    Java SE5的java.util.concurren包中的执行器(executor)将为你管理Thread对象,从而简化并发编程,Executor 在客户端和任务执行之间提供了一个间界层;与客户端直接执行任务不同,这个中介对象将执行任务,Executor 允许你管理异步执行的任务,而无须显示的管理线程生命周期。Executor 是Java SE5/6中启动任务的优选方案

    我们可以使用Executor来代替在MoreBasicThread.java中显示的创建Thread对象。LiftOff对象知道如何运行具体的任务,与命令设计模式一样,它暴露了要执行的单一方法。ExecutorService(具有服务生命周期的Executor,例如关闭)知道如何构建恰当的上下文来执行Runnable对象。在下面的示例中,CachedThreadPool将为每个任务都创建一个线程,注意ExecutorService对象是使用静态的Executor方法创建的,这个方法可以确定其Executor类型:

import java.util.concurrent.*;
public class CachedThreadPool{
 public static void main(String[]args){
  ExecutorService exec=Executors.newCachedThreadPool();
//LiftOff是实现了Runnable接口的类
 for(int i=0;i<5;i++){
  exec.execute(new LiftOff());
  exec.shutdown();
 }
 }
}

非常常见的情况是,单个的Executor被用来创建和管理系统中的所有任务。

对shutdown()方法的调用可以防止新任务被提交给这个Executor,当前线程(在本例中,即驱动main()的线程)将继续运行在shutdown()被调用之前提交的所有任务。这个程序将在Executor中的所有任务完成之后尽快退出。

你可以很容易的将前面示例中的CachedThreadPool替换为不同类型的ExecutorFixedThreadPool使用了有限的线程集来执行所 提交的任务

import java.util.concurrent.*;
public class CachedThreadPool{
 public static void main(String[]args){
  ExecutorService exec=Executors.newFixedThreadPool(5);
//LiftOff是实现了Runnable接口的类
 for(int i=0;i<5;i++){
  exec.execute(new LiftOff());
  exec.shutdown();
 }
 }
}

有了FixedThreadPool,你就可以一次性预先执行代价高昂的线程分配,因而也就可以限制线程的数量了。这样可以节省时间,因为你不用为每个任务都固定地付出创建线程的开销。在事件驱动的系统中,需要线程的事件处理器,通过直接从池中获取线程,也可以如你所愿地尽快得到服务。你不会滥用可获得的资源,因为FixedThreadPool使用的Thread对象的数量是由限制的。

注意,在任何线程池中,现有线程在可能的情况下都会被复用。

尽管使用CachedThreadPool,但是也应该考虑在产生线程的代码中使用FixedThreadPoolCachedThreadPool在程序过程中通常会创建与所需数量相同的线程,然后它在回收旧线程时停止创建新线程,因此它是合理的Executor的首选。只有当这种方式会引发问题时,你才需要切换到FixedThreadPool

SingleThreadPoolExecutor顾名思义,它就像是线程数量为1的FixedThreadPool。这对于你希望在另一个另一个线程中持续运行的任何事务(长期存活的任务)来说,都是很有用的,例如监听进入的套接字连接的任务,它对于希望在线程中运行的短任务也同样很方便,例如,更新本地或远程日志的小任务,或者是事件分发线程。

如果向SingleThreadPoolExecutor提交多个任务,那么这些任务将排队,每个任务都会在下一个任务运行前结束,所有的任务将使用相同的线程池。在下面的示例中,你可以看到每个任务都是按照他们提交的顺序,并且在下一个任务开始之前完成的。因此,SingleThreadPoolExecutor会序列化所有提交给他的任务,它会维护它自己(隐藏)的悬挂任务队列。

import java.util.concurrent.*;
public class CachedThreadPool{
 public static void main(String[]args){
  ExecutorService exec=Executors.newSingleThreadPool();
//LiftOff是实现了Runnable接口的类
 for(int i=0;i<5;i++){
  exec.execute(new LiftOff());
  exec.shutdown();
 }
 }
}
作为另一个示例,假设你有大量的线程,那他们运行的任务将使用文件系统,你可以用 SingleThreadPoolExecutor来运行这些线程,以确保任何时刻在任何线程中都只有唯一的任务在运行。在这种方式中,你不需要在共享资源上处理同步(同时不会过度使用文件系统)。有时更好的解决方案是在资源上同步,但是 SingleThreadPoolExecutor可以让你省去只是为了维持某些事物的原型而进行各种协调努力。通过序列化任务,你可以消除对序列化对象的需求
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值