1)Callable和Future
Runnable封装一个异步运行的任务;可以当成一个没有任何参数和返回值的异步方法,Callable和 Runnable类似,但是它有返回值和参数。
Callable接口是一个参数化的类型,只有一个方法call。
1 public interface Callable<V>
2
3 {
4
5 V call()throws Exception;
6
7 }
类型参数v是指返回值的类型,例如Callable<Integer>代表最终返回一个Integer类型对象的异步计算。
Future保存异步计算的结果。Future接口具有下面的方法:
1 public interface Future<V>
2 {
3
4 V get() throws....;
5
6 V get(long timeout, TimeUnit unit) throws...;
7
8 void cancel(boolean mayInterrupt);
9
10 boolean isCancelled();
11
12 boolean isDone();
13
14
15 }
第一个get方法的调用将被阻塞,直到计算完成,第二个get方法调用,如果计算完成之前超时,将抛出异常;如果计算还在进行,isdone方法返回false;如果想取消计算,调用cancel方法,如果计算还没开始,将永远也不会开始,如果计算已经开始,那么,如果参数mayInterrupt设为true,则被打断。
FutureTask包装器是一种很方便的将Callable转换成Future和Runnable的机制,它同时实现了这两个接口。例如:
1 Callable<Integer> myComputation=....;
2
3 FutureTask<Integer> task=new FutureTask<Integer>(myComputation);
4
5 Thread t=new Thread(task);//it‘s a Runnable;
6
7 t.start();
8
9 ...
10
11 Integer result=task.get();//it‘s a Future;
2)线程池
构建一个新的线程还是需要一些开销的,如果需要创建大量的生存期很短的线程,那就应该使用线程池,一个线程池包含大量的空闲线程;将一个Runnable对象给线程池,线程池中的一个线程就会调用run方法,当run方法结束之后,该线程并不会死亡,而是继续在池中准备为下一个请求提供服务。
执行器(Executor)类有大量用来构建线程池的静态工厂方法,常用的有以下三个方法:
newCachedThreadPool方法,构建一个线程池,对于任务请求,如果有空闲线程可用,立即让它执行任务,否则就创建一个新线程。
newFixedThreadPool方法,构建一个固定大小的线程池,如果提交的任务大于空闲线程的数量,那么得不到服务的任务将被置于等待队列中。
newSingleThreadExecutor,构建一个大小为1的线程池,由一个线程执行所有任务,一个接一个。
使用方法,例如:
1 ExecutorService pool=Executors.newCachedThreadPool();
2
3 Callable<Integer> myComputation=....;
4
5 Future<Integer> task=pool.submit(myComputation);
6
7 ...
8
9 Integer result=task.get();
10
11 pool.shutdown();
2014-07-22 20:53:08