重點是那個股票交易處理程序的例子,認真看三遍。本文花了三個小時。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線程太多了,遺漏這個了.求解.
從輸出能夠看到: