日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程 简洁版

發布時間:2023/12/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程 简洁版 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

多線程技術分享

背景:

以前單CPU,單任務的條件下,一段時間只能執行單一的程序。之后發展到多任務階段。多個任務共享一個CPU,本質上是有操作系統來完成CPU對多個用戶的切換。保證每個任務都有一定的時間片來完成任務。

1.????? 概念和原理

?

進程是指一個內存中運行的應用程序,每個進程都有自己獨立的一塊內存空間,一個進程中可以啟動多個線程。

?

線程是指進程中的一個執行流程,一個進程中可以運行多個線程。線程總是屬于某個進程,進程中的多個線程共享進程的內存。

2.????? 線程的兩種實現方法

1、擴展java.lang.Thread類。

?

此類中有個run()方法,應該注意其用法:

public void run()

如果該線程是使用獨立的 Runnable 運行對象構造的,則調用該 Runnable 對象的 run 方法;否則,該方法不執行任何操作并返回。

Thread 的子類應該重寫該方法。

2、實現java.lang.Runnable接口。

?

void run()

使用實現接口 Runnable 的對象創建一個線程時,啟動該線程將導致在獨立執行的線程中調用對象的 run 方法。

方法 run 的常規協定是,它可能執行任何所需的操作。

?

兩種方式的區別:既然都能實現線程的功能,怎樣區別使用呢。java規定只能單繼承,如果自定義類需要繼承其他類,只能選擇實現Runnable接口。

3. 線程的理解

線程繼承Thread 或者實現Runnable接口。既然是線程,就必然有寫的run方法,其次,多線程是多個線程處理公共的資源,所以,每個線程都共享公用資源,所以每個線程里面都有同一個資源對象。通常,公共資源有線程的構造方法傳遞的。如下,共享資源pendingIfData。

  • /**?
  • ?*?接口調用線程?
  • ?*??
  • ?*?@author?maoping?
  • ?*?
  • ?*/??
  • public?class?ThreadIfExcuse?extends?Thread?{??
  • ??
  • ????//?線程名稱??
  • 10. ????private?String?threadName;??
  • 11. ??
  • 12. ????//?待處理接口數據公共類??
  • 13. ????private?PendingIfData?pendingIfData;??
  • 14. ??
  • 15. ????ThreadIfExcuse(String?threadName,?PendingIfData?pendingIfData)?{??
  • 16. ????????this.threadName?=?threadName;??
  • 17. ????????this.pendingIfData?=?pendingIfData;??
  • 18. ??
  • 19. ????}??
  • 20. ??
  • 21. ????@Override??
  • 22. ????public?void?run()?{??
  • 23. ????????while?(true)?{??
  • 24. ????????????pendingIfData.ifExcuse(threadName);??
  • 25. ????????}??
  • 26. ??
  • 27. ????}??
  • 28. ??
  • 29. }??

    詳細描述共享資源的內容。實現互斥操作的方式有多種,實例中使用await / signal來控制。一般而言,公用共享資源類中包含

    ?

    數據共享的存儲介質,需要線程安全,本示例中為LinkedBlockingQueue類型的interfaceUUIDQueue 。

    ?

    互斥執行方法fExcuse (進入方法使用lock將代碼鎖住,使用條件condition的await,讓代碼線程處于等待狀態。然后是從數據共享的存儲介質中獲取待處理數據,然后執行互斥的業務方法。最后lock解鎖(lock.unlock)。

    ?

    喚醒方法:如果是一個類調用喚醒方法,則是簡單的多線程處理,如果是多個線程調用喚醒方法,則為生產者,消費者,倉庫模型了。喚醒方法的詳情。首先lock鎖定,其次給共享的存儲介質中加入待處理數據單元,然后喚醒添加下等待的線程同時醒來進行一次控制權搶奪。其中一個獲取控制權去處理一個數據。

    ?

  • /**?
  • ?*?待處理接口數據線程?
  • ?*??
  • ?*?@author?maoping?
  • ?*?
  • ?*/??
  • public?class?PendingIfData?{??
  • ??
  • ????private?ReentrantLock?lock?=?new?ReentrantLock();??
  • 10. ??
  • 11. ????private?Condition?condition?=?lock.newCondition();??
  • 12. ??
  • 13. ????private?LinkedBlockingQueue<String>?interfaceUUIDQueue?=?new?LinkedBlockingQueue<String>();??
  • 14. ??
  • 15. ????//?condition?必須在lock鎖范圍內??
  • 16. ????public?void?ifExcuse(String?threadName)?{??
  • 17. ??
  • 18. ????????try?{??
  • 19. ????????????lock.lock();??
  • 20. ????????????condition.await();??
  • 21. ????????????//?接口調用??
  • 22. ????????????String?IfUUID?=?interfaceUUIDQueue.take();??
  • 23. ????????????//?靜態類?不能注入服務?需要使用getBean方式回去服務類??
  • 24. ????????????IfExcuseService?ifExcuseService?=?new?IfExcuseService();??
  • 25. ????????????ifExcuseService.ifExcuse(IfUUID);??
  • 26. ????????}?catch?(InterruptedException?e)?{??
  • 27. ????????????//?TODO?Auto-generated?catch?block??
  • 28. ????????????e.printStackTrace();??
  • 29. ????????}?finally?{??
  • 30. ????????????lock.unlock();??
  • 31. ????????}??
  • 32. ??
  • 33. ????}??
  • 34. ??
  • 35. ????/**?
  • 36. ?????*?添加待調用的線程UUID?并激活等待線程?
  • 37. ?????*??
  • 38. ?????*?@param?IfUUID?
  • 39. ?????*/??
  • 40. ????public?void?putIfUUID(String?IfUUID)?{??
  • 41. ??
  • 42. ????????lock.lock();??
  • 43. ????????try?{??
  • 44. ????????????System.out.println("添加待調用接口UUID?激活調用線程?...?...");??
  • 45. ????????????interfaceUUIDQueue.put(IfUUID);??
  • 46. ????????????condition.signal();??
  • 47. ????????}?catch?(InterruptedException?e)?{??
  • 48. ????????????e.printStackTrace();??
  • 49. ????????}??
  • 50. ????????lock.unlock();??
  • 51. ??
  • 52. ????}??
  • 53. ??
  • 54. }??

    ?

    ?

    4. 線程狀態的切換

    線程的狀態轉換是線程控制的基礎。線程狀態總的可分為五大狀態:分別是生、死、可運行、運行、等待/阻塞。用一個圖來描述如下:

    ?

    ?

    ?

    新建狀態(New):當線程對象對創建后,即進入了新建狀態,如:Thread t = new MyThread();

    就緒狀態(Runnable):當調用線程對象的start()方法(t.start();),線程即進入就緒狀態。處于就緒狀態的線程,只是說明此線程已經做好了準備,隨時等待CPU調度執行,并不是說執行了t.start()此線程立即就會執行;

    運行狀態(Running):當CPU開始調度處于就緒狀態的線程時,此時線程才得以真正執行,即進入到運行狀態。注:就緒狀態是進入到運行狀態的唯一入口,也就是說,線程要想進入運行狀態執行,首先必須處于就緒狀態中;

    阻塞狀態(Blocked):處于運行狀態中的線程由于某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才 有機會再次被CPU調用以進入到運行狀態。根據阻塞產生的原因不同,阻塞狀態又可以分為三種:

    1.等待阻塞:運行狀態中的線程執行wait()方法,使本線程進入到等待阻塞狀態;

    2.同步阻塞 -- 線程在獲取synchronized同步鎖失敗(因為鎖被其它線程所占用),它會進入同步阻塞狀態;

    3.其他阻塞 -- 通過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。

    死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命周期。

    ?

    線程在Running的過程中可能會遇到阻塞(Blocked)情況

  • 調用join()和sleep()方法,sleep()時間結束或被打斷,join()中斷,IO完成都會回到Runnable狀態,等待JVM的調度。
  • 調用wait(),使該線程處于等待池(wait blocked pool),直到notify()/notifyAll(),線程被喚醒被放到鎖定池(lock blocked pool ),釋放同步鎖使線程回到可運行狀態(Runnable)
  • 對Running狀態的線程加同步鎖(Synchronized)使其進入(lock blocked pool ),同步鎖被釋放進入可運行狀態(Runnable)。
  • 此外,在runnable狀態的線程是處于被調度的線程,此時的調度順序是不一定的。Thread類中的yield方法可以讓一個running狀態的線程轉入runnable。

    ?

    ?

    ?

    ?

    5. 線程的各種機制下的示例

    任務場景:一個機構有1000替代幣(類似比特幣),每次放出20個比特幣,放幣的時間間隔為 次數*3秒,放完為止。三個礦工集團(A、B、C)使用計算機挖比特幣。

    用一個線程模擬機構,按照時間規律放替代幣,另外三個線程模擬三個礦工公司挖替代幣。

    ?

  • 公共服務數據類
  • /**?
  • ?*?數據共享服務?
  • ?*??
  • ?*?@author?maoping?
  • ?*?
  • ?*/??
  • public?class?MyCommonData?{??
  • ??
  • 10. ????//?鎖??
  • 11. ????private?ReentrantLock?lock?=?new?ReentrantLock();??
  • 12. ??
  • 13. ????//?條件??
  • 14. ????private?Condition?condition?=?lock.newCondition();??
  • 15. ??
  • 16. ????//?倉庫??
  • 17. ????private?LinkedBlockingQueue<Integer>?bitMoneyQueue?=?new?LinkedBlockingQueue<Integer>();??
  • 18. ??
  • 19. ????//?礦工挖到比特幣??
  • 20. ????public?void?getBitMoney(String?threadName)?{??
  • 21. ????????try?{??
  • 22. ????????????lock.lock();??
  • 23. ????????????condition.await();//?處于阻塞狀態??
  • 24. ????????????Integer?moneyCode?=?bitMoneyQueue.take();//?比特幣編碼??
  • 25. ????????????System.out.println(threadName?+?"?挖到了比特幣,編碼為:"?+?moneyCode);??
  • 26. ????????}?catch?(InterruptedException?e)?{??
  • 27. ????????????e.printStackTrace();??
  • 28. ????????}?finally?{??
  • 29. ????????????lock.unlock();??
  • 30. ????????}??
  • 31. ????}??
  • 32. ??
  • 33. ????public?void?createBitCoin(Integer?bitCoinCode)?{??
  • 34. ????????try?{??
  • 35. ????????????lock.lock();??
  • 36. ????????????bitMoneyQueue.put(bitCoinCode);??
  • 37. ????????????condition.signal();??
  • 38. ????????}?catch?(InterruptedException?e)?{??
  • 39. ????????????e.printStackTrace();??
  • 40. ????????}?finally?{??
  • 41. ????????????lock.unlock();??
  • 42. ????????}??
  • 43. ??
  • 44. ????}??
  • 45. ??
  • 46. }??

    ?

    2.生產數據類(此處使用單線程模擬不斷生成新的比特幣)

  • /**?
  • ?*?創建替代幣公司?
  • ?*??
  • ?*?@author?maoping?
  • ?*?
  • ?*/??
  • public?class?CreateBitCoinThread?extends?Thread?{??
  • ??
  • ????//?共享數據??
  • 10. ????private?MyCommonData?commonData;??
  • 11. ??
  • 12. ????private?int?count?=?0;??
  • 13. ??
  • 14. ????CreateBitCoinThread(MyCommonData?commonData)?{??
  • 15. ????????this.commonData?=?commonData;??
  • 16. ??
  • 17. ????}??
  • 18. ??
  • 19. ????@Override??
  • 20. ????public?void?run()?{??
  • 21. ????????System.out.println("begin?...");??
  • 22. ????????long?nextCreateBitCoinTime?=?System.currentTimeMillis();??
  • 23. ????????long2date("首次時間為?",?nextCreateBitCoinTime);??
  • 24. ????????while?(true)?{??
  • 25. ????????????if?(count?<=?500?&&?nextCreateBitCoinTime?<?System.currentTimeMillis())?{??
  • 26. ????????????????for?(int?i?=?0;?i?<?20;?i++)?{??
  • 27. ????????????????????System.out.println("");??
  • 28. ????????????????????commonData.createBitCoin(count?*?20?+?i?+?1);??
  • 29. ????????????????}??
  • 30. ????????????????nextCreateBitCoinTime?+=?((count?+?1)?*?1000)?*?10;??
  • 31. ????????????????long2date("下次時間為?",?nextCreateBitCoinTime);??
  • 32. ????????????????count++;??
  • 33. ????????????}??
  • 34. ????????}??
  • 35. ????}??
  • 36. ??
  • 37. ????private?void?long2date(String?str,?long?dateTime)?{??
  • 38. ????????SimpleDateFormat?sdf?=?new?SimpleDateFormat("MM/dd/yyyy?HH:mm:ss");??
  • 39. ????????java.util.Date?dt?=?new?Date(dateTime);??
  • 40. ????????String?sDateTime?=?sdf.format(dt);?//?得到精確到秒的表示:08/31/2006?21:08:00??
  • 41. ????????System.out.println(str?+?"?"?+?sDateTime);??
  • 42. ????}??
  • 43. ??
  • 44. }??

    3.多線程消費數據類

  • /**?
  • ?*?創建替代幣公司?
  • ?*??
  • ?*?@author?maoping?
  • ?*?
  • ?*/??
  • public?class?CreateBitCoinThread?extends?Thread?{??
  • ??
  • ????//?共享數據??
  • 10. ????private?MyCommonData?commonData;??
  • 11. ??
  • 12. ????private?int?count?=?0;??
  • 13. ??
  • 14. ????CreateBitCoinThread(MyCommonData?commonData)?{??
  • 15. ????????this.commonData?=?commonData;??
  • 16. ??
  • 17. ????}??
  • 18. ??
  • 19. ????@Override??
  • 20. ????public?void?run()?{??
  • 21. ????????System.out.println("begin?...");??
  • 22. ????????long?nextCreateBitCoinTime?=?System.currentTimeMillis();??
  • 23. ????????long2date("首次時間為?",?nextCreateBitCoinTime);??
  • 24. ????????while?(true)?{??
  • 25. ????????????if?(count?<=?500?&&?nextCreateBitCoinTime?<?System.currentTimeMillis())?{??
  • 26. ????????????????for?(int?i?=?0;?i?<?20;?i++)?{??
  • 27. ????????????????????System.out.println("");??
  • 28. ????????????????????commonData.createBitCoin(count?*?20?+?i?+?1);??
  • 29. ????????????????}??
  • 30. ????????????????nextCreateBitCoinTime?+=?((count?+?1)?*?1000)?*?10;??
  • 31. ????????????????long2date("下次時間為?",?nextCreateBitCoinTime);??
  • 32. ????????????????count++;??
  • 33. ????????????}??
  • 34. ????????}??
  • 35. ????}??
  • 36. ??
  • 37. ????private?void?long2date(String?str,?long?dateTime)?{??
  • 38. ????????SimpleDateFormat?sdf?=?new?SimpleDateFormat("MM/dd/yyyy?HH:mm:ss");??
  • 39. ????????java.util.Date?dt?=?new?Date(dateTime);??
  • 40. ????????String?sDateTime?=?sdf.format(dt);?//?得到精確到秒的表示:08/31/2006?21:08:00??
  • 41. ????????System.out.println(str?+?"?"?+?sDateTime);??
  • 42. ????}??
  • 43. ??
  • 44. }??

  • main方法主類
  • ?

  • /**?
  • ?*?main?方法主類?
  • ?*??
  • ?*?@author?maoping?
  • ?*?
  • 10. ?*/??
  • 11. public?class?MainTest?{??

  • 12. ??
  • 13. ????public?static?void?main(String[]?args)?{??
  • 14. ??
  • 15. ????????MyCommonData?commonData?=?new?MyCommonData();??
  • 16. ????????new?Thread(new?CreateBitCoinThread(commonData)).start();??
  • 17. ????????//?礦工挖礦??
  • 18. ????????new?Thread(new?DigBitcoinThread(commonData,?"挖礦公司?A")).start();??
  • 19. ????????new?Thread(new?DigBitcoinThread(commonData,?"挖礦公司?B")).start();??
  • 20. ????????new?Thread(new?DigBitcoinThread(commonData,?"挖礦公司?C")).start();??
  • 21. ??
  • 22. ????}??
  • 23. ??
  • 24. }??

  • 運行結果類
  • begin?...??
  • 首次時間為??03/26/2018?09:23:37??
  • ??
  • ??
  • ??
  • 挖礦公司?A?挖到了比特幣,編碼為:1??
  • 挖礦公司?B?挖到了比特幣,編碼為:2??
  • ??
  • 挖礦公司?C?挖到了比特幣,編碼為:3??
  • ??
  • 挖礦公司?A?挖到了比特幣,編碼為:4??
  • ??
  • 挖礦公司?B?挖到了比特幣,編碼為:5??
  • ??
  • 挖礦公司?C?挖到了比特幣,編碼為:6??
  • ??
  • 挖礦公司?A?挖到了比特幣,編碼為:7??
  • ??
  • 挖礦公司?B?挖到了比特幣,編碼為:8??
  • ??
  • 挖礦公司?C?挖到了比特幣,編碼為:9??
  • ??
  • 挖礦公司?A?挖到了比特幣,編碼為:10??
  • ??
  • 挖礦公司?B?挖到了比特幣,編碼為:11??
  • ??
  • 挖礦公司?C?挖到了比特幣,編碼為:12??
  • ??
  • 挖礦公司?A?挖到了比特幣,編碼為:13??
  • ??
  • 挖礦公司?B?挖到了比特幣,編碼為:14??
  • ??
  • 挖礦公司?C?挖到了比特幣,編碼為:15??
  • ??
  • 挖礦公司?A?挖到了比特幣,編碼為:16??
  • ??
  • 挖礦公司?B?挖到了比特幣,編碼為:17??
  • ??
  • 挖礦公司?C?挖到了比特幣,編碼為:18??
  • ??
  • 挖礦公司?A?挖到了比特幣,編碼為:19??
  • 挖礦公司?B?挖到了比特幣,編碼為:20??
  • 下次時間為??03/26/2018?09:23:47??
  • ??
  • -----------------------??
  • ??
  • ??
  • ??
  • 挖礦公司?C?挖到了比特幣,編碼為:21??
  • 挖礦公司?A?挖到了比特幣,編碼為:22??
  • ??
  • ??
  • ??
  • 挖礦公司?B?挖到了比特幣,編碼為:23??
  • 挖礦公司?C?挖到了比特幣,編碼為:24??
  • 挖礦公司?A?挖到了比特幣,編碼為:25??
  • ??
  • ??
  • ??
  • 挖礦公司?B?挖到了比特幣,編碼為:26??
  • 挖礦公司?C?挖到了比特幣,編碼為:27??
  • 挖礦公司?A?挖到了比特幣,編碼為:28??
  • ??
  • ??
  • ??
  • ??
  • 挖礦公司?B?挖到了比特幣,編碼為:29??
  • 挖礦公司?C?挖到了比特幣,編碼為:30??
  • 挖礦公司?A?挖到了比特幣,編碼為:31??
  • ??
  • 挖礦公司?B?挖到了比特幣,編碼為:32??
  • ??
  • ??
  • ??
  • ??
  • ??
  • 挖礦公司?C?挖到了比特幣,編碼為:33??
  • 挖礦公司?A?挖到了比特幣,編碼為:34??
  • 挖礦公司?B?挖到了比特幣,編碼為:35??
  • ??
  • 挖礦公司?C?挖到了比特幣,編碼為:36??
  • 挖礦公司?A?挖到了比特幣,編碼為:37??
  • 下次時間為??03/26/2018?09:24:07??
  • ??
  • -----------------------------??
  • ??
  • ??
  • 挖礦公司?B?挖到了比特幣,編碼為:38??
  • ??
  • ??
  • 挖礦公司?C?挖到了比特幣,編碼為:39??
  • 挖礦公司?A?挖到了比特幣,編碼為:40??
  • ??
  • 100.挖礦公司?B?挖到了比特幣,編碼為:41??

    102.挖礦公司?C?挖到了比特幣,編碼為:42??

    105.挖礦公司?A?挖到了比特幣,編碼為:43??

    106.挖礦公司?B?挖到了比特幣,編碼為:44??

    108.挖礦公司?C?挖到了比特幣,編碼為:45??

    110.挖礦公司?A?挖到了比特幣,編碼為:46??

    112.挖礦公司?B?挖到了比特幣,編碼為:47??

    114.挖礦公司?C?挖到了比特幣,編碼為:48??

    116.挖礦公司?A?挖到了比特幣,編碼為:49??

    118.挖礦公司?B?挖到了比特幣,編碼為:50??

    120.挖礦公司?C?挖到了比特幣,編碼為:51??

    122.挖礦公司?A?挖到了比特幣,編碼為:52??

    124.挖礦公司?B?挖到了比特幣,編碼為:53??

    126.挖礦公司?C?挖到了比特幣,編碼為:54??

    128.挖礦公司?A?挖到了比特幣,編碼為:55??

    130.挖礦公司?B?挖到了比特幣,編碼為:56??

    131.挖礦公司?C?挖到了比特幣,編碼為:57??

    132.下次時間為??03/26/2018?09:24:37??

    由結果可以看出,每次放出20個比特幣,且每次放出時間間隔逐漸變成,第一次間隔10s 第二次間隔20s,第三次間隔30s 依次重復。且每次放出的20個比特幣被三個挖礦公司挖走。3個挖礦公司為相互競爭每次放出固定數量的比特幣。比特幣只能被其中的一個公司挖走。使用多線程描述這一情景。

    ?

    轉載于:https://www.cnblogs.com/maopneo/p/8648816.html

    總結

    以上是生活随笔為你收集整理的多线程 简洁版的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。