本文共 5392 字,大约阅读时间需要 17 分钟。
目录
当运行N个并发任务来解决同一个问题时,你只希望获取最早返回的结果,那么可以使用invokeAny方法。
模拟用户验证,一个通过接口方式验证,另一个使用数据库方式验证。只要其中一种方式验证通过即返回结果。
package xyz.jangle.thread.test.n4_4.invokeany;import java.util.ArrayList;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * 4.4、运行N个任务并处理第一个(最先的且正常的)返回结果 * 案例:模拟用户验证,一个通过接口方式验证,另一个使用数据库方式验证。 * 只要其中一种方式验证通过即返回结果。 * @author jangle * @email jangle@jangle.xyz * @time 2020年8月19日 下午5:38:03 * */public class M { public static void main(String[] args) { var user = "user"; var password = "password"; var iValidator = new UserValidator("接口验证"); var dbValidator = new UserValidator("数据库验证"); var iTask = new ValidatorTask(iValidator, user, password); var dbTask = new ValidatorTask(dbValidator, user, password); ArrayListtaskList = new ArrayList (); taskList.add(iTask); taskList.add(dbTask); ExecutorService threadPool = Executors.newCachedThreadPool(); String result; try { result = threadPool.invokeAny(taskList); System.out.println("Main:result:使用了"+result); } catch (InterruptedException e) { System.out.println("Main:中断异常"); e.printStackTrace(); }catch (ExecutionException e) { // 用户验证失败,两种方式都未正确返回。 System.out.println("Main:用户验证失败"); e.printStackTrace(); } threadPool.shutdown(); System.out.println("Main:执行结束"); }}
package xyz.jangle.thread.test.n4_4.invokeany;import java.util.Random;import java.util.concurrent.TimeUnit;/** * 用户校验类 * @author jangle * @email jangle@jangle.xyz * @time 2020年8月19日 下午5:39:08 * */public class UserValidator { private final String name; public UserValidator(String name) { super(); this.name = name; } public boolean validate(String name, String password) { var r = new Random(); long duration = (long) (Math.random() * 10); System.out.println(this.name + "验证使用时间:" + duration); try { // 模拟验证时长 TimeUnit.SECONDS.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); return false; } // 采用随机方式模拟用户验证,即1/2的概率验证通过。 return r.nextBoolean(); } public String getName() { return name; } }
package xyz.jangle.thread.test.n4_4.invokeany;import java.util.concurrent.Callable;/** * 执行验证的任务线程 * * @author jangle * @email jangle@jangle.xyz * @time 2020年8月19日 下午5:44:10 * */public class ValidatorTask implements Callable{ private final UserValidator validator; private final String user; private final String password; public ValidatorTask(UserValidator validator, String user, String password) { super(); this.validator = validator; this.user = user; this.password = password; } @Override public String call() throws Exception { if (!validator.validate(user, password)) { System.out.println(validator.getName() + ":用户验证不通过"); throw new Exception("用户验证失败"); } System.out.println(validator.getName() + ":用户验证通过"); // 返回用户验证的方式 return validator.getName(); }}
4.1、接口验证不通过,数据库验证通过。返回数据库验证结果。(使用了第二个正确的结果)
数据库验证验证使用时间:9接口验证验证使用时间:1接口验证:用户验证不通过数据库验证:用户验证通过Main:result:使用了数据库验证Main:执行结束
4.2、接口验证通过,返回接口验证结果(然后中断数据库验证的线程。使用了第一个正确的接口,中断第二个任务的执行)。
接口验证验证使用时间:0数据库验证验证使用时间:3接口验证:用户验证通过Main:result:使用了接口验证Main:执行结束java.lang.InterruptedException: sleep interrupted at java.base/java.lang.Thread.sleep(Native Method) at java.base/java.lang.Thread.sleep(Thread.java:339) at java.base/java.util.concurrent.TimeUnit.sleep(TimeUnit.java:446) at xyz.jangle.thread.test.n4_4.invokeany.UserValidator.validate(UserValidator.java:28) at xyz.jangle.thread.test.n4_4.invokeany.ValidatorTask.call(ValidatorTask.java:28) at xyz.jangle.thread.test.n4_4.invokeany.ValidatorTask.call(ValidatorTask.java:1) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834)数据库验证:用户验证不通过
4.3、都不通过(抛出ExecutionException异常)
数据库验证验证使用时间:4接口验证验证使用时间:3接口验证:用户验证不通过数据库验证:用户验证不通过Main:用户验证失败java.util.concurrent.ExecutionException: java.lang.Exception: 用户验证失败 at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) at java.base/java.util.concurrent.AbstractExecutorService.doInvokeAny(AbstractExecutorService.java:199) at java.base/java.util.concurrent.AbstractExecutorService.invokeAny(AbstractExecutorService.java:220) at xyz.jangle.thread.test.n4_4.invokeany.M.main(M.java:32)Caused by: java.lang.Exception: 用户验证失败 at xyz.jangle.thread.test.n4_4.invokeany.ValidatorTask.call(ValidatorTask.java:30) at xyz.jangle.thread.test.n4_4.invokeany.ValidatorTask.call(ValidatorTask.java:1) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834)Main:执行结束
转载地址:http://bbsvb.baihongyu.com/