4.运行多个任务并处理第一个结果
并发编程中的常见问题就是,当采用多个并发任务解决一个问题时,往往只关心这些任务的第一个结果。这里我们使用ThreadPoolExecutor类实现该场景。
范例允许用户通过两种验证机制进行验证,但是只要有一种机制验证成功,那么这个用户就验证通过了。
关键在于ThreadPoolExecutor类的方法invokeAny()方法接收到一个任务列表,然后运行任务,返回第一个完成任务且没有抛出异常的任务执行结果。
这个方法返回的类型与任务里的call()
方法返回的类型相同,在这个范例中,将返回String类型的值。
这里有两个任务可以番红花true值,或者抛出Exception异常。因此有下面四种情况
1.如果两个任务都返回true值,那么InvokeAny()方法的结果就是首次完成任务的名称。
2.如果第一个任务返回true值,第二个任务抛出Exception异常,那么invokeAny方法的结果就是第一个任务的名称。
3.如果第一个任务抛出Exception异常,第二个任务返回true值,那么InvokeAny()方法的结果就是第二个任务的名称。
4.如果两个任务都抛出异常Exception,那么InvokeAny()方法将抛出ExecutionException异常。
该方法还有一个其他版本
invokeAny(Collection<? extends Callable<T>> tasks, long timeout,TimeUnit timeUnit),这个方法执行所有的任务,如果在给定的时间内某个任务已经完成,则返回其结果。
3.Main 测试类
5.运行多个任务并处理所有结果
如果想要等待任务的结束,可以使用下面的方法:
1.如果任务执行结束,那么Future接口的isDone()方法将返回true。
2.在调用shutdown()方法后,ThreadPoolExecutor类的awaitTermination()方法会将线程休眠,直到所有的任务都执行完毕。
这两个方法有一些缺点
1.方法一中仅仅可以控制任务的完成与否。
2.方法二中必须关闭执行器来等待一个线程,否则调用这个方法的线程将立即返回。
ThreadPoolExecutor类还提供了一个方法,允许发送一个任务列表给执行器,并等待列表中所有任务执行完成。该方法就是InvokeAll(),返回一个List的Future对象。
关于InvokeAll()方法的重要地方,就是使用Future对象仅用来获取任务的结果。
当所有的任务执行结束时这个方法也执行结束了,如果在返回的Future对象上调用isDone()方法,那么所有的调用将返回true值。
另一个版本的方法:
InvokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit timeUnit)当所有的任务都执行完毕,或者超时的时候(无论哪个首先发生),
这个方法将返回
保持任务状态和结果的Future列表。
3.Main测试类
并发编程中的常见问题就是,当采用多个并发任务解决一个问题时,往往只关心这些任务的第一个结果。这里我们使用ThreadPoolExecutor类实现该场景。
范例允许用户通过两种验证机制进行验证,但是只要有一种机制验证成功,那么这个用户就验证通过了。
关键在于ThreadPoolExecutor类的方法invokeAny()方法接收到一个任务列表,然后运行任务,返回第一个完成任务且没有抛出异常的任务执行结果。
这个方法返回的类型与任务里的call()
方法返回的类型相同,在这个范例中,将返回String类型的值。
这里有两个任务可以番红花true值,或者抛出Exception异常。因此有下面四种情况
1.如果两个任务都返回true值,那么InvokeAny()方法的结果就是首次完成任务的名称。
2.如果第一个任务返回true值,第二个任务抛出Exception异常,那么invokeAny方法的结果就是第一个任务的名称。
3.如果第一个任务抛出Exception异常,第二个任务返回true值,那么InvokeAny()方法的结果就是第二个任务的名称。
4.如果两个任务都抛出异常Exception,那么InvokeAny()方法将抛出ExecutionException异常。
该方法还有一个其他版本
invokeAny(Collection<? extends Callable<T>> tasks, long timeout,TimeUnit timeUnit),这个方法执行所有的任务,如果在给定的时间内某个任务已经完成,则返回其结果。
实例代码:
1、验证任务类
public class TaskValidator implements Callable<String>{
private UserValidator validator;
private String user;
private String password;
public TaskValidator(UserValidator validator, String user, String password) {
this.validator = validator;
this.user = user;
this.password = password;
}
@Override
public String call() throws Exception {
if(!validator.validate(user, password)){
System.out.printf("%s: The user has not been found\n",validator.getName());
throw new Exception("Erro validating user");
}
System.out.printf("%s The user has been fund\n",validator.getName());
return validator.getName();
}
}
2.用户验证
/**
*
* @author fcs
* @date 2015-5-5
* 描述:运行多个任务并处理第一个结果
* 说明:
*/
public class UserValidator {
private String name;
public UserValidator(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean validate(String name,String password){
Random random = new Random();
//模拟处理时间
long duration = (long)(Math.random() *10);
System.out.printf("Validator %s: validating a user during %d seconds\n",this.name,duration);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
//返回随机的Boolean值,表示是否通过验证
return random.nextBoolean();
}
}
3.Main 测试类
public class Main {
public static void main(String[] args) {
String user = "test";
String password = "test";
UserValidator user1 = new UserValidator("LDAP");
UserValidator user2 = new UserValidator("DataBase");
TaskValidator task1 = new TaskValidator(user1, user, password);
TaskValidator task2 = new TaskValidator(user2, user, password);
List<TaskValidator> task1List = new ArrayList<TaskValidator>();
task1List.add(task1);
task1List.add(task2);
ExecutorService executor = (ExecutorService)Executors.newCachedThreadPool();
String result;
try{
result = executor.invokeAny(task1List);
System.out.printf("Main : Result: %s\n",result);
}catch(Exception e){
e.printStackTrace();
}
executor.shutdown(); //终止执行器
System.out.println("Main : End of the execution");
}
}
5.运行多个任务并处理所有结果
如果想要等待任务的结束,可以使用下面的方法:
1.如果任务执行结束,那么Future接口的isDone()方法将返回true。
2.在调用shutdown()方法后,ThreadPoolExecutor类的awaitTermination()方法会将线程休眠,直到所有的任务都执行完毕。
这两个方法有一些缺点
1.方法一中仅仅可以控制任务的完成与否。
2.方法二中必须关闭执行器来等待一个线程,否则调用这个方法的线程将立即返回。
ThreadPoolExecutor类还提供了一个方法,允许发送一个任务列表给执行器,并等待列表中所有任务执行完成。该方法就是InvokeAll(),返回一个List的Future对象。
关于InvokeAll()方法的重要地方,就是使用Future对象仅用来获取任务的结果。
当所有的任务执行结束时这个方法也执行结束了,如果在返回的Future对象上调用isDone()方法,那么所有的调用将返回true值。
另一个版本的方法:
InvokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit timeUnit)当所有的任务都执行完毕,或者超时的时候(无论哪个首先发生),
这个方法将返回
保持任务状态和结果的Future列表。
实例代码:
1.存储实例中并发任务产生的结果
/**
*
* @author fcs
* @date 2015-5-5
* 描述:运行多个任务并处理所有结果
* 说明:
*/
public class Result {
<span style="white-space:pre"> </span>private String name;
<span style="white-space:pre"> </span>private int value;
<span style="white-space:pre"> </span>public String getName() {
<span style="white-space:pre"> </span>return name;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public void setName(String name) {
<span style="white-space:pre"> </span>this.name = name;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public int getValue() {
<span style="white-space:pre"> </span>return value;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public void setValue(int value) {
<span style="white-space:pre"> </span>this.value = value;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
}
2.Task类
public class Task implements Callable<Result> {
private String name;
public Task(String name) {
this.name = name;
}
@Override
public Result call() throws Exception {
System.out.printf("%s: Starting\n",this.name);
long duration = (long)(Math.random() * 10);
System.out.printf("%s: waiting %d seconds for results\n",this.name,duration);
TimeUnit.SECONDS.sleep(duration);
int value = 0;
for(int i =0 ;i< 5;i++){
value+=(int)(Math.random() * 100);
}
Result result = new Result();
result.setName(this.name);
result.setValue(value);
return result;
}
}
3.Main测试类
public class Main {
public static void main(String[] args) {
ExecutorService executor = (ExecutorService)Executors.newCachedThreadPool();
List<Task> taskList = new ArrayList<Task>();
for(int i =0 ;i < 3;i++){
Task task = new Task(i+"");
taskList.add(task);
}
List<Future<Result>> resultList = null;
try {
//该方法返回上一步创建的Future类型的列表
resultList = executor.invokeAll(taskList);
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown();
System.out.println("Main: Printing the results");
for(int i =0;i< resultList.size();i++){
Future<Result> future = resultList.get(i);
try {
Result result = future.get();
System.out.println(result.getName()+" : "+result.getValue());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}