JDK5中增加了Doug Lea的并发库,这一引进给java线程的管理和使用提供了强大的便利性。 java.util.current包中提供了对线程优化、管理的各项操作,使得线程的使用变得得心应手。该包提供了线程的运行线程池的创建线程生命周期的控制线程间的协作等功能。

一、核心API介绍
1、Executor接口
public void execute(Runnable runnable);
该接口声明了execute方法,将Runnable对象传入,调用该方法相当于启动了该线程

2、ExecutorService接口
该接口是Executor的子接口,提供了submit方法,该方法返回Future对象,Future可用于控制线程的执行与取消

3、ScheduledExecutorService接口
该接口是ExecutorService的子接口,提供了线程启动时机的控制。

4、Callable接口
提供了如下方法
public Object call() throws Exception;
该接口类似Runnable接口,只是有返回值和抛出的异常,该方法返回的值就是ExecutorService接口调用submit(Callable call)方法后,其返回的Future对象调用get方法后返回的值。

5、Future接口
Future接口用于控制线程的执行

调用cancel(boolean bool)方法将会取消正在运行的进程。
另外ExecutorService的shutDown()方法将启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用;shutDownNow()方法试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。

6、Executors
这是一个线程池的工厂类,该类提供了许多生成Executor,ExecutorService,ScheduleExecutorService的工厂方法。

其实,Executor就相当于一个线程池,提供对线程的管理功能,包括启动线程,取消线程执行,加入线程,移除线程,以及协调线程之间的工作等功能,这些随着Executor级别(即子接口,实现类)越高而功能越强。

二、应用简介
1、启动一个线程

 
  
  1. Executor executor = Executors.newFixedThreadPool(3); 
  2. executor.execute(new Runnable() { 
  3.     public void run() { 
  4.         // your code 
  5.     } 
  6. }); 

也可以启动Callable形式的线程

 
  
  1. ExecutorService executor = Executors.newFixedThreadPool(3); 
  2. executor.submit(new Callable() { 
  3.     public Object call() throws Exception { 
  4.         Object o = null
  5.         // your code; 
  6.         return o; 
  7.     } 
  8. }); 

注意,以上的方法每执行一次就运行一次Runnable或Callable对象的run(),call()方法,如果生成的Executor对象指定了数目,例如上面中是3,则当调用execute方法或submit方法时到达3次以上时,实际上同时运行的线程最多只有3个,是按照顺序的(即多出来的,后放进去的线程没有运行),只有当Executor池中正在运行的线程少于3个(即某些线程处于idle空虚状态,不在运行了),其后多出来的线程才会开始运行(按调用执行的顺序),但任何时候最多只能有3个线程运行。
同一个线程可以被执行多次,多次调用执行方法就行了。

2、取消线程的执行
当想终止线程的执行时,可以调用Future的cancel方法,但也不一定能够终止;另外如果是ExecutorSrvice,也可以调用shutDownNow或者shutDown方法。shutDown方法将等待当前的线程执行完毕后终止所有的线程,而shutDownNow试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。

3、顺序执行线程

 
  
  1. ExecutorService executor = Executors.newFixedThreadPool(3); 
  2. Future future = executor.submit(r1); //r1是Runnable或Callable实例 
  3. future.get(); 
  4. executor.submit(r2); //r2是Runnable或Callable实例

以上代码将会使r1执行完后再执行r2,因为Future的get方法具有阻塞调用者线程的功能,执行get方法时,将会等待Future对应的线程执行完毕后才会返回结果,其会阻塞调用者线程

4、从线程池中添加与移除线程
要移除线程,则需要ExecutorService接口的实现类ThreadPoolExecutor或其子类的方法。
在线程池中添加线程:
调用execute或submit方法都可以将线程加入线程池,对同一个线程重复调用也可以,也相当于调用2个不同线程,只不过执行相同的代码。
在线程池中删除线程:
public boolean remove(Runnable task)
从执行程序的内部队列中移除此任务(如果存在),从而如果尚未开始,则其不再运行,如果已经删除则返回true
public void purge()
尝试从工作队列移除所有已取消的 Future 任务。

5、线程的协作
利用CyclicBarrier可以协调线程的之间的运行,它允许一组线程互相等待,直到到达某个公共屏障点。
例如有一项工作需要有2个人完成,而这项工作有2个步骤,只有在执行第一个步骤只后,才可以执行第二个步骤,每一个步骤都需要2个人参与。这时可以使用CyclicBarrier了。2个人代表2个线程,如下。

 
  
  1. public class CyclicBarrierTest { 
  2.  
  3.     public static void main(String args[]) { 
  4.         CyclicBarrier barrier = new CyclicBarrier(2); 
  5.         Work work = new Work(barrier); 
  6.         Worker worker1 = new Worker(work, 0); 
  7.         Worker worker2 = new Worker(work, 0); 
  8.         Executor executor = Executors.newFixedThreadPool(2); 
  9.         executor.execute(worker1); 
  10.         executor.execute(worker2); 
  11.     } 
  12.  
  13. class Worker implements Runnable { 
  14.     private Work work; 
  15.     private int speed; 
  16.  
  17.     public Worker(Work work, int speed) { 
  18.         this.work = work; 
  19.         this.speed = speed; 
  20.     } 
  21.  
  22.     public void run() { 
  23.         work.worked(speed); 
  24.     } 
  25.  
  26. class Work { 
  27.     private CyclicBarrier barrier; 
  28.  
  29.     public Work(CyclicBarrier barrier) { 
  30.  
  31.         this.barrier = barrier; 
  32.     } 
  33.  
  34.     public void worked(int speed) { 
  35.         firstWork(speed); 
  36.         secondWork(); 
  37.     } 
  38.  
  39.     private void firstWork(int speed) { 
  40.         try { 
  41.             barrier.await(); 
  42.             Thread.sleep(speed); 
  43.         } catch (Exception e) { 
  44.         } 
  45.     } 
  46.  
  47.     private void secondWork() { 
  48.         try { 
  49.             barrier.await(); 
  50.         } catch (Exception e) { 
  51.         } 
  52.     } 

6、线程池的线程回收
CompletionService 是一个管理执行完毕的线程的类,以Executor为参数构造实例。submit方法用于提交任务,似乎是委派给Executor执行,而take()方 法则是获取并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则等待。,pool也类似只不过当时没有时返回null并不等待。

原文地址:http://blog.sina.com.cn/hss117