重点是那个股票交易处理程序的例子,认真看三遍。本文花了三个小时。java
GitHub代码欢迎star。git
小白认为学习语言最好的方式就是模仿、思考别人为何这么写。github
FutureTask类同时实现类Runnable接口和Future接口。所以,FutureTask类技能拥有Runnable接口提供的异步计算能力,也能拥有Future接口提供的返回值给调用方的Future对象取消任务的能力。FutureTask类能够用于封装Callable和Runnable接口。数组
//Future<Integer> future = executor.submit(Callable); FutureTask<Integer> future = new FutureTaks<Integer>(Callable); future.run()
run方法会调用任务,并将任务的计算结果赋值给Future对象。dom
也能够将FutureTask实例交给Executor对象用于执行。异步
executor.submit(future);
因为FutureTask类也实现了Future接口,所以FutureTak接口实例能够用来取消任务,检查任务等。ide
取消任务可使用执行器返回的Future对象,而建立和执行任务可使用前面讨论的FutureTask类。函数
开发能够处理上百万次请求的模拟器。会发送数千条数据交易请求给模拟器。模拟器包含的线程池用于处理这些请求。
还将编写一个“邪恶”的线程,它会随机选择诺干订单,而且尝试取消他们。若是订单已经执行,取消请求会失败。
若是在订单在被分配给线程执行以前接收到取消请求,那么订单会被取消。若是交易订单正在执行。而且线程可被中断,
那么在订单处理过程当中接收的取消请求会结束剩余的处理流程。从而取消订单。学习
/** * Created by guo on 2018/2/15. * 演示可取消任务的股票交易处理程序 */ public class StocksOrderProcessor { static final int MAX_NUMBER_OF_ORDER = 1_000_000; //交易订单 //一、建立数量为1000的线程池来执行订单。通过测试1000个线程,CPU维持在70%-80%左右。 static private ExecutorService executor = Executors.newFixedThreadPool(1000); //二、建立ArrayList来保存执行执行订单的引用 static private List<Future> ordersToProcess = new ArrayList<>(); /** * 建立内部私有类OrderExecutor以处理订单执行的业务逻辑。 * OrderExecutor实现了Callable接口以支持异步调用。 */ public static class OrderExecutor implements Callable { int id = 0; int count = 0; //三、传入整型变量id来记录订单编号。 public OrderExecutor(int id) { this.id = id; } @Override public Object call() throws Exception { try { //四、将技术设为1000,每次计数前,让线程休眠一段不一样的时间 while (count < 1000) { count++; //五、经过让线程休眠一段不一样的时间,模拟现实中每一个订单须要不一样的处理时间。 Thread.sleep(new Random( System.currentTimeMillis() % 10).nextInt(10)); } System.out.println("Successfully executed order:" + id); } catch (Exception ex) { throw (ex); } return id; } } }
public static void main(String[] args) { System.out.printf("Submitting %d trades%n", MAX_NUMBER_OF_ORDER); //六、经过循环遍历,提交一百万订单。 for (int i = 0; i < MAX_NUMBER_OF_ORDER; i++) { submitOrder(i); } //七、建立“邪恶”线程尝试随机的取消某些订单。 //每当执行到这里时,就会建立一些取消请求,并针对待处理的订单列表中存储的Future对象执行。 new Thread(new EvilThread(ordersToProcess)).start(); System.out.println("Cancelling a few order at random"); try { //8a、某些订单可能已经被处理,模拟器就会继续处理剩余订单。 // b、若是订单在执行器分配线程以前被取消,就将永远不会执行。 // c、为了留有足够的时间结束全部待处理的订单,让执行器等待30秒。 executor.awaitTermination(30, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Checking status before shutdown"); int count = 0; //9a、经过循环遍历,统计有多少订单被成功取消。 // b、对于订单中每个Future对象,调用isCancelld方法。 // c、若是对应的被成功取消,则方法返回true for (Future f : ordersToProcess) { if (f.isCancelled()) { count++; } } System.out.printf("%d trades cancelled%n", count); //十、当即中止执行器释放分配的全部资源 (貌似个人百万订单根本停不下来啊,求解!) executor.shutdownNow(); } private static void submitOrder(int id) { //六、a 建立一个Callable实例,每一个实例都有为一个的Id供跟踪 Callable<Integer> callable = new OrderExecutor(id); //六、b 调用ExecutorService的submit方法可将建立的任务提交以待执行。 //而且将submit方法返回的对象放到待处理订单的数组里列表中。 ordersToProcess.add(executor.submit(callable)); }
/** * 邪恶线程,随机的取消某些订单。 */ class EvilThread implements Runnable { private List<Future> ordersToProcess; //一、在构造函数中传入待处理的订单列表,这样能够对某一些Future对象发送取消请求。 public EvilThread(List<Future> future) { this.ordersToProcess = future; } @Override public void run() { //二、建立100个取消请求 Random myNextKill = new Random(System.currentTimeMillis() % 100); for (int i = 0; i < 100; i++) { //三、随机选择Future对象进行取消。 int index = myNextKill.nextInt(StocksOrderProcessor.MAX_NUMBER_OF_ORDER); //四、调用Future对象的cancel方法以发送请求,并将cancel方法的参数设为ture。表示任务可能会在执行过程当中被中断。 boolean cancel = ordersToProcess.get(index).cancel(true); //五、判断是否取消成功, if (cancel) { System.out.println("Cancel Order Succeded:" + index); } else { System.out.println("cancel Order Failed:" + index); } try { //六、在每两个请求之间让“邪恶”线程睡一会。 Thread.sleep(myNextKill.nextInt(100)); } catch (InterruptedException e) { e.printStackTrace(); } } } }
程序运行后部分输出以下:测试
Submitting 1000000 trades Successfully executed order:28 Successfully executed order:380 Successfully executed order:288 Successfully executed order:120 Cancelling a few order at random Successfully executed order:116 Successfully executed order:1004 Successfully executed order:1005 Cancel Order Succeded:698021 cancel Order Failed:98832(重点) ... Successfully executed order:12268 Successfully executed order:12420 Successfully executed order:13190 Successfully executed order:12199 Checking status before shutdown 99 trades cancelled(重点) Successfully executed order:14045 //估计Kill线程太多了,遗漏这个了.求解.
从输出能够看到: