在上一篇文章中我们已经了解了Executor框架进行线程管理,这篇文章将学习Executor框架的另一个特性,我们知道执行Runnable任务是没有返回值得,但Executor可以运行并发任务并获得返回值,Concurrent包提供下面两个接口实现这个功能:
- Callable接口:这个接口声明call(),类似于Runnable的run(),可以在这个方法里实现任务的具体逻辑操作。Callable是一个泛型接口,必须声明call()的返回类型。
- Future接口:这个接口声明了一下方法来获取Callable的返回数据。
使用方法
通过Executor的submit()提交Callable任务执行,这个Submit()方法将会返回Future对象。利用Future对象可以:
- 使用isDone()方法,查看任务是否完成。
- 通过get()方法获call()方法执行的返回值,这个方法会一直等待callable对象执行完call()方法并返回结果。如果出现中断,get()方法会抛出InterruptedException,或者call()方法抛出的异常。
package MyThread;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
public class ExecutorTest {
public static void main(String[] args){
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
ArrayList<Future<String>> list=new ArrayList<>();
for (int i = 0; i < 5; i++){
Future<String> result=executor.submit(new task());
list.add(result);
}
for(Future<String> f:list){
try {
//while(!f.isDone()){};
System.out.println(f.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
executor.shutdown();
}
}
class task implements Callable<String>{
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
Random random=new Random();
int result=random.nextInt(100);
// 第二阶段——等待所有选手准备好
Thread.sleep((long) (random.nextInt(5) * 1000));
return Thread.currentThread().getName()+":"+result;
}
}
结果:
pool-1-thread-1:84
pool-1-thread-2:78
pool-1-thread-3:15
pool-1-thread-4:99
pool-1-thread-5:2
运行多个任务并处理所以结果:
ThreadPoolExecutor通过一个 invokeAll()方法,支持将多个Callable任务放进集合当中,并等待所有任务完成,再把结果返回到Future的链表当中。
与submit()不同,invokeAll()会阻塞直到所以得任务都执行完成。
例如:
package MyThread;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
public class ExecutorTest {
public static void main(String[] args){
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
//任务链表
List<task> tasklist=new ArrayList<>();
//结果链表
List<Future<String>> resultlist=new ArrayList<>();
for (int i = 0; i < 5; i++){
tasklist.add(new task());
}
try {
resultlist=executor.invokeAll(tasklist);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("获取执行结果:");
for(Future<String> f:resultlist){
try {
// while(!f.isDone()){};
System.out.println(f.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
executor.shutdown();
}
}
class task implements Callable<String>{
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
Random random=new Random();
int result=random.nextInt(100);
// 第二阶段——等待所有选手准备好
Thread.sleep((long) (random.nextInt(5) * 1000));
return Thread.currentThread().getName()+":"+result;
}
}
时间: 2024-10-23 17:44:09