線程2---異步1

  在Java中什么是同步?什么是異步?對于這兩個概念我們必須要明確。只有明確這兩個概念,才會在明確在什么場景下使用同步以及異步。

  在這里我可以形象的舉個例子來辨明這兩個概念:

1.同步與異步
同步和異步關注的是消息通信機制 (synchronous communication/ asynchronous communication)
所謂同步,就是在發出一個*調用*時,在沒有得到結果之前,該*調用*就不返回。但是一旦調用返回,就得到返回值了。換句話說,就是由*調用者*主動等待這個*調用*的結果。
而異步則是相反,*調用*在發出之后,這個調用就直接返回了,所以沒有返回結果。換句話說,當一個異步過程調用發出后,調用者不會立刻得到結果。而是在*調用*發出后,*被調用者*通過狀態、通知來通知調用者,或通過回調函數處理這個調用。
典型的異步編程模型舉個通俗的例子:你打電話問書店老板有沒有《分布式系統》這本書,
如果是同步通信機制,書店老板會說,你稍等,”我查一下",然后開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。
而異步通信機制,書店老板直接告訴你我查一下啊,查好了打電話給你,然后直接掛電話了(不返回結果)。然后查好了,他會主動打電話給你。
在這里老板通過“回電”這種方式來回調。
2. 阻塞與非阻塞阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態.阻塞調用是指調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之后才會返回。非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程。還是上面的例子,
你打電話問書店老板有沒有《分布式系統》這本書,你如果是阻塞式調用,你會一直把自己“掛起”,直到得到這本書有沒有的結果,如果是非阻塞式調用,你不管老板有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老板有沒有返回結果。在這里阻塞與非阻塞與是否同步異步無關。跟老板通過什么方式回答你結果無關。
在開始解決上述問題之前我們來討論下使用Callbale接口來創建線程。
@FunctionalInterface
public interface Callable<V> {/*** 返回一個任務的結果,或者拋出一個異常(如果不能計算結果)*/V call() throws Exception;
}

Callable接口是一個函數式接口,其中call()方法的返回值的類型就是Callable接口的泛型的類型。但是Callable接口怎么和線程扯上關系呢?? FutureTask類存在一個構造器:如下所示:

FutureTask(Callable<V> callable) 

其中的參數正式Callable接口對象;FutureTask類又是實現接口RunnableFuture接口:

public class FutureTask<V> implements RunnableFuture<V>

接著看:

public interface RunnableFuture<V> extends Runnable, Future<V> {void run();
}

最終的還是繼承了Runnable接口和Future接口,為了說明關系,我們畫出類圖:

package com._thread;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class CallableThread implements Callable<String> {/*** 票的張數為50張,總共100個人買票*/private int ticket = 50;// 表示票的張數
@Overridepublic String call() throws Exception {for (int i = 0; i < 100; i++) {if (ticket > 0) {System.out.println("買票:ticket = " + this.ticket--);}}return "票賣光了!";}public static void main(String[] args) throws InterruptedException, ExecutionException {// 創建Callable接口對象  在這里我創建了兩個任務對象Callable<String> callable1 = new CallableThread();Callable<String> callable2 = new CallableThread();// 將創建的callable任務對象存儲在FutureTask對象中FutureTask<String> task1=new FutureTask<String>(callable1);FutureTask<String> task2=new FutureTask<String>(callable2);// 啟動線程執行任務new Thread(task1).start();new Thread(task2).start();// 上述代碼只是執行線程,callable接口是可以產生結果的,futuretask可以獲取結果// 調用get()方法可以阻止當前執行的線程獲取結果System.out.println("線程A的返回結果是:"+task1.get());System.out.println("線程B的返回結果是:"+task2.get());}
}

這是使用callable接口來創建線程的一種實現過程;好了現在讓我們討論Java異步編程吧!

上面的圖可以說明我們的一個買書的過程,在Java中可以視這個操作為同步操作:

package com._thread;public class SlowWorker {public SlowWorker() {}public void doWork() {try {System.out.println("==== 找書, 找書, 找書 ====== ");Thread.sleep(2000);System.out.println("==== OK! ======");} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {SlowWorker worker = new SlowWorker();// 主線程模擬買書的人,doWork()方法模擬書店老板的行為!System.out.println("老板,我要買書" + new java.util.Date());worker.doWork();System.out.println("... 老板在找書的過程中我可以干些事情嗎!....");System.out.println("書買到了" + new java.util.Date());System.exit(0);}
}

看運行結果:

老板,我要買書Sun Jan 21 01:49:35 CST 2018
==== 找書, 找書, 找書 ====== 
==== OK! ======
... 老板在找書的過程中我可以干些事情嗎!....
書買到了Sun Jan 21 01:49:37 CST 2018

以上的操作確實是一種同步的操作;主線程運行開始后,調用doWork()方法,而doWork()方法需要休眠2s.但是主線程沒有繼續執行,而是等待了,大家是不是感覺這樣做事很沒有效率。換言之,如果你在書店買書,老板找一天,你會持續等待下去嗎?

接下來我們談談ExecutorService這個接口,它可以表示線程池對象;當線程空閑時,它可以接受一個提交給ExecutorService的callable對象,當線程結束的時候,他會返回一個Future.

package com._thread;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;/*** 異步編程* @author gosaint**/
public class AsynchronousWorker {public AsynchronousWorker() {}public void doWork() {try {System.out.println("==== 找書, 找書, 找書 ====== ");Thread.sleep(2000);System.out.println("==== OK! ======");} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {SlowWorker worker = new SlowWorker();// 主線程模擬買書的人,doWork()方法模擬書店老板的行為!System.out.println("老板,我要買書" + new java.util.Date());// 此時我們創建一個線程池,個數為3ExecutorService service = Executors.newFixedThreadPool(3);// 此時存在一個線程池對象,線程池對象提交任務,是一個callable接口Future<String> future = service.submit(new Callable<String>() {@Overridepublic String call() throws Exception {new AsynchronousWorker().doWork(); return null;}});System.out.println("... 老板在找書的過程中我可以干些事情嗎!....");System.out.println("做愛做的事情!");try {//調用此方法可以獲取我們任務的執行結果,但是會阻止主線程的運行,直到得到一個結果
                future.get(); } catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}System.out.println("書買到了" + new java.util.Date());System.exit(0);}}

運行結果如下:

老板,我要買書Sun Jan 21 02:16:13 CST 2018
... 老板在找書的過程中我可以干些事情嗎!....
做愛做的事情!
==== 找書, 找書, 找書 ====== 
==== OK! ======
書買到了Sun Jan 21 02:16:15 CST 2018

 主線程開始運行,接著我們向ExecutorService提交了一個買書的任務,之后我們在干其他的事情。而最后呢,Future對象從ExecutorService獲取到了執行的結果。我們調用get()方法獲取到了執行的結果;倘若我們沒有這個調用,那么還是一個并行計算,那么老板找書的結果不會立馬給我們返回的; 

轉載于:https://www.cnblogs.com/gosaint/p/8320866.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/452979.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/452979.shtml
英文地址,請注明出處:http://en.pswp.cn/news/452979.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql通常使用語句_Mysql 常用SQL語句集錦

基礎篇//查詢時間&#xff0c;友好提示$sql "select date_format(create_time, %Y-%m-%d) as day from table_name";//int 時間戳類型$sql "select from_unixtime(create_time, %Y-%m-%d) as day from table_name";//一個sql返回多個總數$sql "sel…

為什么你需要設計和維護一套自我移動標準?

在一個很長的調研日的休息時分&#xff0c;我在同一個客戶談一個項目&#xff0c;在這個項目中&#xff0c;我正為一個全球經濟公司開發一個iOS標準。他們的第一反應是這樣的&#xff1a;“什么&#xff1f;你在開發Apple iOS以外的標準&#xff1f;那還要開發什么&#xff1f;…

JS 小知識點匯總

1.offsetWidth & width A:因為. 1.offsetWidth是只讀屬性&#xff0c;而style.width是可讀寫得。2.offsetWidth返回的是一個整數&#xff0c;style.width返回的是一個字符串,并且帶有單位&#xff1b;**3.style.width只能返回以style方式定義的內部樣式的width屬性值。4.of…

django-redis中redis.conf配置詳細說明

參考文獻&#xff1a;https://blog.csdn.net/ljphilp/article/details/52934933 感謝樓主分享&#xff01;

初識Mysql(一)

1 搭建數據庫服務器2 MYSQL數據類型3 修改表結構1 搭建數據庫服務器1.1 存在mariadb時&#xff1a;#systemctl status mariadb#systemctl stop mariadb#rpm -e --nodeps mariadb-libs #不依賴關系卸載#rm -rf /etc/my.cnf#rm -rf /var/lib/mysql/*1.2 新安裝時[rootser51 ~]# …

數據挖掘資料

https://blog.csdn.net/baimafujinji/article/details/53269040 在2006年12月召開的 IEEE 數據挖掘國際會議上&#xff08;ICDM&#xff0c; International Conference on Data Mining&#xff09;&#xff0c;與會的各位專家選出了當時的十大數據挖掘算法&#xff08; top 10 …

如何進行個人知識管理和提高自己能力?

21世紀是一個知識爆炸的世紀&#xff0c;知識爆炸是指人類創造的知識,主要是自然科學知識,在短時期內以極高的速度增長起來。是人們對當前大量出現并飛速發展的各種知識現象所進行的夸張和描述。有人綜合計算,全世界的知識總量,七到十年翻一番。這就是風行全球的摩登名詞的意思…

redis服務器端和客戶端啟動

服務器端 sudo redis-server /etc/redis/redis.conf 指定加載的配置文件 ps -ef|grep redis 查看redis服務器進程 sudo kill -9 pid 殺死redis服務器 連接特定IP的redis&#xff1a;

hive表移到mysql_如何將Hive數據表移動到MySql?

我想知道如何將日期從Hive轉移到MySQL&#xff1f;我已經看到了如何將hive數據移動到Amazon DynamoDB而不是像MySQL這樣的RDBMS的示例.以下是我在DynamoDB中看到的示例&#xff1a;CREATE EXTERNAL TABLE tbl1 ( name string, location string )STORED BY org.apache.hadoop.hi…

賬簿與平衡段關聯表

gl_ledger_norm_seg_vals轉載于:https://www.cnblogs.com/lizicheng/p/8817982.html

超級丑數

題目&#xff1a; 寫一個程序來找第 n 個超級丑數。超級丑數的定義是正整數并且所有的質數因子都在所給定的一個大小為 k 的質數集合內。比如給你 4 個質數的集合 [2, 7, 13, 19], 那么 [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] 是前 12 個超級丑數。注意事項&#xff1a;…

為什么要進行個人知識管理(PKM)

21世紀是一個知識爆炸的世紀&#xff0c;知識爆炸是指人類創造的知識,主要是自然科學知識,在短時期內以極高的速度增長起來。是人們對當前大量出現并飛速發展的各種知識現象所進行的夸張和描述。有人綜合計算,全世界的知識總量,七到十年翻一番。這就是風行全球的摩登名詞的意思…

Python中“if __name__=='__main__':”理解與總結

具體詳解參考文獻&#xff1a;https://www.cnblogs.com/chenhuabin/p/10118199.html

python中列表如何比較大小_如何比較python中的列表/列表?

所以你想要兩個項目列表之間的區別。 first_list = [[Test.doc, 1a1a1a, 1111], [Test2.doc, 2b2b2b, 2222], [Test3.doc, 3c3c3c, 3333]] secnd_list = [[Test.doc, 1a1a1a, 1111], [Test2.doc, 2b2b2b, 2222], [Test3.doc, 8p8p8p, 9999], [Test4.doc, 4d4d4d, 4444]] 首先,…

NFC讀卡------ci522

1、NFC及卡片 NFC是近距離無線通訊技術&#xff0c;是一種非接觸式識別和互聯技術&#xff0c;可以在移動設備、消費類電子產品、PC和智能控件工具間進行近距離無線通信。NFC提供了一種簡單、觸控式的解決方案&#xff0c;可以讓消費者簡單直觀地交換信息、訪問內容與服務。 …

java基礎面試題:說說和的區別

&與&&都是邏輯與 不同的是&左右兩邊的判斷都要進行&#xff0c;而&&是短路與&#xff0c;當&&左邊條件為假則不用再判斷右邊條件&#xff0c;所以效率更高 例如&#xff0c;對于if(str ! null && !str.equals(“”))表達式&#xff0c…

codeforce 457DIV2 C題

題意 你需要構造一個n個點m條邊的無向有權圖&#xff0c;要求這個圖的MST中邊權的和與從1到n的最短路長度都為素數 分析 可以想到這樣一種貪心&#xff0c;在i到i1直接連一條邊&#xff0c;這樣最短路和MST都會是同樣的一些邊。只要保證他們的和為素數就好&#xff0c;對于其他…

何必言精通——十年雜感

30虛歲了。這一、兩年&#xff0c;有事沒事之中口中經常念著李商隱那首《錦瑟》&#xff1a; 錦瑟無端五十弦&#xff0c;一弦一柱思華年。莊生曉夢迷蝴蝶&#xff1b;望帝春心托杜鵑。滄海月明珠有淚&#xff1b;藍田日暖玉生煙。此情可待成追憶&#xff0c;只是當時已惘然。…