Java多線程Future模式

來源:互聯網
上載者:User

標籤:state   主函數   調用   call()   之間   param   blog   str   方式   

Java多線程Future模式有些類似於Ajax的非同步請求
Future模式的核心在於:去除了主函數的等待時間,並使得原本需要等待的時間段可以用於處理其他商務邏輯
假設伺服器的處理某個業務,該業務可以分成AB兩個過程,並且AB兩個過程之間不需要彼此的返回結果A過程需要1秒鐘,B過程需要2秒鐘,主線程其他動作2秒鐘
按照正常編寫,程式大概需要執行5秒
如果按照Future模式只需要執行2秒(取其中已耗用時間最久的線程的已耗用時間)

Future模式的核心實現在於兩個方面

1.多線程運行
  主線程採用多線的方式,運行幾個業務無關的任務來節省主線的等待時間。
2.鎖的鎖定和釋放
  子線程執行指定的任務時,需要保證主線程能正確的擷取子線程的返回資料
  這裡分兩種情況
  (1)子線程的已耗用時間要大於主線程處理其他業務的時間,此時主線程需要擷取子線程的傳回值,而子線程卻還沒有執行完畢,
    所以在這個時候需要讓主線程進入等待。子線程執行完畢以後立刻喚醒主線程。
  (2)子線程的已耗用時間小於主線處理其他業務的時間,此時無需要等待。

知識要點:
  1、wait(),notify()需要和synchronized一塊使用,去掉會報 java.lang.IllegalMonitorStateException
  1>當前線程不含有當前對象的鎖資源的時候,調用obj.wait()方法;
  2>當前線程不含有當前對象的鎖資源的時候,調用obj.notify()方法。
  3>當前線程不含有當前對象的鎖資源的時候,調用obj.notifyAll()方法。
  2、wait()方法會釋放鎖


Service類比伺服器處理業務的過程
package future;import java.util.Date;/** * 伺服器 *  * @author wpy *  */public class Service {/** * 1.伺服器的處理某個業務,該業務可以分成AB兩個過程,並且AB兩個過程之間不需要彼此的返回結果 * 2.A過程需要1秒鐘,B過程需要2秒鐘,主線程其他動作2秒鐘 *  * @param args * @throws InterruptedException */public static void main(String[] args) throws InterruptedException {Service service = new Service();long notUseFuture = service.notUseFuture();System.out.println("==============================");long useFuture = service.useFuture();System.out.println("==============================");System.out.println("notUseFuture整個業務耗時"+notUseFuture);System.out.println("useFuture整個業務耗時"+useFuture);}public long useFuture() throws InterruptedException {Date startOn = new Date();String name = Thread.currentThread().getName();final FutureDate<String> futureDateA = new FutureDate<>();final FutureDate<String> futureDateB = new FutureDate<>();Thread a = new Thread(new Runnable() {@Overridepublic void run() {String name = Thread.currentThread().getName();System.out.println(name + ":任務A開始執行");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}futureDateA.setData(name + ":任務A執行結果");System.out.println(name + ":任務A執行結束");}}, "線程A");Thread b = new Thread(new Runnable() {@Overridepublic void run() {String name = Thread.currentThread().getName();System.out.println(name + ":任務B開始執行");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}futureDateB.setData(name + ":任務B執行結果");System.out.println(name + ":任務B執行結束");}}, "線程B");Date before = new Date();a.start();b.start();Date after = new Date();System.out.println(name + ":a,b阻塞主線程時間:"+ (after.getTime() - before.getTime()));// 假設其他業務執行兩秒鐘Thread.sleep(2000);before = new Date();String dataA = futureDateA.getData();after = new Date();System.out.println(name + ":擷取A線程結果時間:"+ (after.getTime() - before.getTime()));before = new Date();String dataB = futureDateB.getData();after = new Date();System.out.println(name + ":擷取線程結果時間:"+ (after.getTime() - before.getTime()));System.out.println(name + ":A線程結果:" + dataA);System.out.println(name + ":B線程結果:" + dataB);Date endOn = new Date();/*System.out.println(name + "整個業務耗時"+ (endOn.getTime() - startOn.getTime()));*/return endOn.getTime() - startOn.getTime();}public long notUseFuture() throws InterruptedException {Date startOn = new Date();// 任務AString name = Thread.currentThread().getName();System.out.println(name + ":任務A開始執行");Thread.sleep(1000);System.out.println(name + ":任務A執行結束");// 任務BSystem.out.println(name + ":任務B開始執行");Thread.sleep(3000);System.out.println(name + ":任務B執行結束");// 主線程其他動作Thread.sleep(2000);Date endOn = new Date();return endOn.getTime() - startOn.getTime();}}

  

封裝的FutrueData類
package future;/** * 使用者擷取非同步任務執行結果 * @author wpy * */public class FutureDate<T> {private boolean isReady = false;private T data;/** * 非同步任務執行完畢後會通過此方法將執行結果傳遞給data; * @param data */public synchronized void setData(T data){if(isReady){return;}this.data = data;isReady = true;notify();}/** * 如果資料沒有載入完畢,線程積蓄等待 * wait()會釋放鎖 * @return * @throws InterruptedException */public synchronized T getData() throws InterruptedException{if(!isReady){wait();}return data;}}

 執行結果

main:任務A開始執行main:任務A執行結束main:任務B開始執行main:任務B執行結束==============================main:a,b阻塞主線程時間:0線程A:任務A開始執行線程B:任務B開始執行線程A:任務A執行結束main:擷取A線程結果時間:0線程B:任務B執行結束main:擷取線程結果時間:1001main:A線程結果:線程A:任務A執行結果main:B線程結果:線程B:任務B執行結果==============================notUseFuture整個業務耗時6001useFuture整個業務耗時3006

 

 

JDK封裝的Future簡單使用

package test;import java.util.Date;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;public class TestFuture {public static void main(String[] args) throws InterruptedException, ExecutionException {Callable<Object> callable = new Callable<Object>() {@Overridepublic Object call() throws Exception {System.out.println(Thread.currentThread().getName()+":正在構造資料");Thread.sleep(1000);System.out.println(Thread.currentThread().getName()+":構造資料資料完畢");return "結果";}};Date before = new Date();FutureTask<Object> futureTask = new FutureTask<>(callable);new Thread(futureTask).start();Thread.sleep(1000);Date after = new Date();System.out.println((after.getTime() - before.getTime())/1000);before = new Date();System.out.println(Thread.currentThread().getName()+":主程式準備擷取結果");Object object = futureTask.get();after = new Date();System.out.println((after.getTime() - before.getTime())/1000);System.out.println(object);}}

  

Java多線程Future模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.