摘要:并且線程可被中斷,那么在訂單處理過程中接收的取消請求會結束剩余的處理流程。演示可取消任務的股票交易處理程序交易訂單創建數量為的線程池來執行訂單。邪惡線程邪惡線程,隨機的取消某些訂單。判斷是否取消成功,在每兩個請求之間讓邪惡線程睡一會。
FutureTask類
重點是那個股票交易處理程序的例子,認真看三遍。本文花了三個小時。
GitHub代碼歡迎star。
小白認為學習語言最好的方式就是模仿、思考別人為什么這么寫。
FutureTask類同時實現類Runnable接口和Future接口。因此,FutureTask類技能擁有Runnable接口提供的異步計算能力,也能擁有Future接口提供的返回值給調用方的Future對象取消任務的能力。FutureTask類可以用于封裝Callable和Runnable接口。
//Futurefuture = executor.submit(Callable); FutureTask future = new FutureTaks (Callable); future.run()
run方法會調用任務,并將任務的計算結果賦值給Future對象。
也可以將FutureTask實例交給Executor對象用于執行。
executor.submit(future);
由于FutureTask類也實現了Future接口,因此FutureTak接口實例可以用來取消任務,檢查任務等。
創建可取消的任務。取消任務可以使用執行器返回的Future對象,而創建和執行任務可以使用前面討論的FutureTask類。
開發可以處理上百萬次請求的模擬器。會發送數千條數據交易請求給模擬器。模擬器包含的線程池用于處理這些請求。
還將編寫一個“邪惡”的線程,它會隨機選擇諾干訂單,并且嘗試取消他們。如果訂單已經執行,取消請求會失敗。
如果在訂單在被分配給線程執行之前接收到取消請求,那么訂單會被取消。如果交易訂單正在執行。并且線程可被中斷,
那么在訂單處理過程中接收的取消請求會結束剩余的處理流程。從而取消訂單。
/** * Created by guo on 2018/2/15. * 演示可取消任務的股票交易處理程序 */ public class StocksOrderProcessor { static final int MAX_NUMBER_OF_ORDER = 1_000_000; //交易訂單 //1、創建數量為1000的線程池來執行訂單。經過測試1000個線程,CPU維持在70%-80%左右。 static private ExecutorService executor = Executors.newFixedThreadPool(1000); //2、創建ArrayList來保存執行執行訂單的引用 static private List主函數ordersToProcess = new ArrayList<>(); /** * 創建內部私有類OrderExecutor以處理訂單執行的業務邏輯。 * OrderExecutor實現了Callable接口以支持異步調用。 */ public static class OrderExecutor implements Callable { int id = 0; int count = 0; //3、傳入整型變量id來記錄訂單編號。 public OrderExecutor(int id) { this.id = id; } @Override public Object call() throws Exception { try { //4、將技術設為1000,每次計數前,讓線程休眠一段不同的時間 while (count < 1000) { count++; //5、通過讓線程休眠一段不同的時間,模擬現實中每個訂單需要不同的處理時間。 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); //6、通過循環遍歷,提交一百萬訂單。 for (int i = 0; i < MAX_NUMBER_OF_ORDER; i++) { submitOrder(i); } //7、創建“邪惡”線程嘗試隨機的取消某些訂單。 //每當執行到這里時,就會創建一些取消請求,并針對待處理的訂單列表中存儲的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); //10、立即停止執行器釋放分配的所有資源 (貌似我的百萬訂單根本停不下來啊,求解!) executor.shutdownNow(); } private static void submitOrder(int id) { //6、a 創建一個Callable實例,每個實例都有為一個的Id供跟蹤 Callable邪惡線程callable = new OrderExecutor(id); //6、b 調用ExecutorService的submit方法可將創建的任務提交以待執行。 //并且將submit方法返回的對象放到待處理訂單的數組里列表中。 ordersToProcess.add(executor.submit(callable)); }
/** * 邪惡線程,隨機的取消某些訂單。 */ class EvilThread implements Runnable { private ListordersToProcess; //1、在構造函數中傳入待處理的訂單列表,這樣可以對某一些Future對象發送取消請求。 public EvilThread(List future) { this.ordersToProcess = future; } @Override public void run() { //2、創建100個取消請求 Random myNextKill = new Random(System.currentTimeMillis() % 100); for (int i = 0; i < 100; i++) { //3、隨機選擇Future對象進行取消。 int index = myNextKill.nextInt(StocksOrderProcessor.MAX_NUMBER_OF_ORDER); //4、調用Future對象的cancel方法以發送請求,并將cancel方法的參數設為ture。表示任務可能會在執行過程中被中斷。 boolean cancel = ordersToProcess.get(index).cancel(true); //5、判斷是否取消成功, if (cancel) { System.out.println("Cancel Order Succeded:" + index); } else { System.out.println("cancel Order Failed:" + index); } try { //6、在每兩個請求之間讓“邪惡”線程睡一會。 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線程太多了,遺漏這個了.求解.
從輸出可以看到:
訂單698021被成功取消,這個訂單還未執行,
訂單98832的取消請求失敗了,因為這個訂單已經執行結束.
在發送的100個請請求中,有99個被成功取下.也可能是100%,取決你的電腦配置.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68496.html
摘要:本文首發于一世流云的專欄一模式簡介模式是多線程設計模式中的一種常見模式,它的主要作用就是異步地執行任務,并在需要的時候獲取結果。二中的模式在多線程基礎之模式中,我們曾經給出過模式的通用類關系圖。 showImg(https://segmentfault.com/img/bVbiwcx?w=1000&h=667); 本文首發于一世流云的專欄:https://segmentfault.co...
摘要:與基于數組的隊列相同,重載的構造函數可以接受集合指定的初始值。這種隊列比基于數組阻塞隊列具有更高的吞吐量。創建個交易者實例,將自己出售的訂單放入隊列中,每個出售訂單都將會有隨機的交易量。要使用基于優先級的隊列,需要提供適當的比較器。 阻塞隊列 在阻塞隊列的幫助下,許多同步問題都可以被公式化。阻塞隊列是隊列,當線程試圖對空隊列進行出列操作,或試圖向滿的隊列中插入條目時,隊列就會阻塞。直到...
摘要:使用進行并行編程在中進行并行編程最常用的方式是繼承類或者實現接口。從開始提供了和兩個接口,通過使用它們可以在任務執行完畢后得到執行結果。 使用Callable、Future進行并行編程 在Java中進行并行編程最常用的方式是繼承Thread類或者實現Runnable接口。這兩種方式的缺點是在任務完成后無法直接獲取執行結果,必須通過共享變量或線程間通信,使用起來很不方便。從Java 1....
摘要:類重點是那個病毒掃描程序的例子,認真看三遍。會從線程池中選擇線程,并將對象提交給線程任務。比如病毒掃描,你可以使用類實現的執行器服務,每小時運行一次病毒掃描。該應用是以固定頻率執行的病毒掃描程序。 Executors類 重點是那個病毒掃描程序的例子,認真看三遍。本文花了四個小時。 GitHub代碼歡迎star。 小白認為學習語言最好的方式就是模仿、思考別人為什么這么寫。結合栗子效果更好...
摘要:有三種狀態運行關閉終止。類類,提供了一系列工廠方法用于創建線程池,返回的線程池都實現了接口。線程池的大小一旦達到最大值就會保持不變,在提交新任務,任務將會進入等待隊列中等待。此線程池支持定時以及周期性執行任務的需求。 這是java高并發系列第19篇文章。 本文主要內容 介紹Executor框架相關內容 介紹Executor 介紹ExecutorService 介紹線程池ThreadP...
閱讀 781·2021-11-09 09:47
閱讀 1568·2019-08-30 15:44
閱讀 1143·2019-08-26 13:46
閱讀 2107·2019-08-26 13:41
閱讀 1266·2019-08-26 13:32
閱讀 3772·2019-08-26 10:35
閱讀 3519·2019-08-23 17:16
閱讀 448·2019-08-23 17:07