国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Java線程間的通信方式詳解

2019-11-26 14:20:48
字體:
來源:轉載
供稿:網友

本總結我對于JAVA多線程中線程之間的通信方式的理解,主要以代碼結合文字的方式來討論線程間的通信,故摘抄了書中的一些示例代碼,具體內容如下

①同步

這里講的同步是指多個線程通過synchronized關鍵字這種方式來實現線程間的通信。

參考示例:

public class MyObject { synchronized public void methodA() {  //do something.... } synchronized public void methodB() {  //do some other thing }}public class ThreadA extends Thread { private MyObject object;//省略構造方法 @Override public void run() {  super.run();  object.methodA(); }}public class ThreadB extends Thread { private MyObject object;//省略構造方法 @Override public void run() {  super.run();  object.methodB(); }}public class Run { public static void main(String[] args) {  MyObject object = new MyObject();  //線程A與線程B 持有的是同一個對象:object  ThreadA a = new ThreadA(object);  ThreadB b = new ThreadB(object);  a.start();  b.start(); }}

由于線程A和線程B持有同一個MyObject類的對象object,盡管這兩個線程需要調用不同的方法,但是它們是同步執行的,比如:線程B需要等待線程A執行完了methodA()方法之后,它才能執行methodB()方法。這樣,線程A和線程B就實現了 通信。

這種方式,本質上就是“共享內存”式的通信。多個線程需要訪問同一個共享變量,誰拿到了鎖(獲得了訪問權限),誰就可以執行。

②while輪詢的方式

代碼如下:

import java.util.ArrayList;import java.util.List;public class MyList { private List<String> list = new ArrayList<String>(); public void add() {  list.add("elements"); } public int size() {  return list.size(); }}import mylist.MyList;public class ThreadA extends Thread { private MyList list; public ThreadA(MyList list) {  super();  this.list = list; } @Override public void run() {  try {   for (int i = 0; i < 10; i++) {    list.add();    System.out.println("添加了" + (i + 1) + "個元素");    Thread.sleep(1000);   }  } catch (InterruptedException e) {   e.printStackTrace();  } }}import mylist.MyList;public class ThreadB extends Thread { private MyList list; public ThreadB(MyList list) {  super();  this.list = list; } @Override public void run() {  try {   while (true) {    if (list.size() == 5) {     System.out.println("==5, 線程b準備退出了");     throw new InterruptedException();    }   }  } catch (InterruptedException e) {   e.printStackTrace();  } }}import mylist.MyList;import extthread.ThreadA;import extthread.ThreadB;public class Test { public static void main(String[] args) {  MyList service = new MyList();  ThreadA a = new ThreadA(service);  a.setName("A");  a.start();  ThreadB b = new ThreadB(service);  b.setName("B");  b.start(); }}

在這種方式下,線程A不斷地改變條件,線程ThreadB不停地通過while語句檢測這個條件(list.size()==5)是否成立 ,從而實現了線程間的通信。但是這種方式會浪費CPU資源。之所以說它浪費資源,是因為JVM調度器將CPU交給線程B執行時,它沒做啥“有用”的工作,只是在不斷地測試 某個條件是否成立。就類似于現實生活中,某個人一直看著手機屏幕是否有電話來了,而不是: 在干別的事情,當有電話來時,響鈴通知TA電話來了。關于線程的輪詢的影響,可參考:Java中一個線程執行死循環有什么后果

 ③wait/notify機制

代碼如下:

import java.util.ArrayList;import java.util.List;public class MyList { private static List<String> list = new ArrayList<String>(); public static void add() {  list.add("anyString"); } public static int size() {  return list.size(); }}public class ThreadA extends Thread { private Object lock; public ThreadA(Object lock) {  super();  this.lock = lock; } @Override public void run() {  try {   synchronized (lock) {    if (MyList.size() != 5) {     System.out.println("wait begin "       + System.currentTimeMillis());     lock.wait();     System.out.println("wait end "       + System.currentTimeMillis());    }   }  } catch (InterruptedException e) {   e.printStackTrace();  } }}public class ThreadB extends Thread { private Object lock; public ThreadB(Object lock) {  super();  this.lock = lock; } @Override public void run() {  try {   synchronized (lock) {    for (int i = 0; i < 10; i++) {     MyList.add();     if (MyList.size() == 5) {      lock.notify();      System.out.println("已經發出了通知");     }     System.out.println("添加了" + (i + 1) + "個元素!");     Thread.sleep(1000);    }   }  } catch (InterruptedException e) {   e.printStackTrace();  } }}public class Run { public static void main(String[] args) {  try {   Object lock = new Object();   ThreadA a = new ThreadA(lock);   a.start();   Thread.sleep(50);   ThreadB b = new ThreadB(lock);   b.start();  } catch (InterruptedException e) {   e.printStackTrace();  } }}

線程A要等待某個條件滿足時(list.size()==5),才執行操作。線程B則向list中添加元素,改變list 的size。

A,B之間如何通信的呢?也就是說,線程A如何知道 list.size() 已經為5了呢?

這里用到了Object類的 wait() 和 notify() 方法。

當條件未滿足時(list.size() !=5),線程A調用wait() 放棄CPU,并進入阻塞狀態。---不像②while輪詢那樣占用CPU

當條件滿足時,線程B調用 notify()通知 線程A,所謂通知線程A,就是喚醒線程A,并讓它進入可運行狀態。

這種方式的一個好處就是CPU的利用率提高了。

但是也有一些缺點:比如,線程B先執行,一下子添加了5個元素并調用了notify()發送了通知,而此時線程A還執行;當線程A執行并調用wait()時,那它永遠就不可能被喚醒了。因為,線程B已經發了通知了,以后不再發通知了。這說明:通知過早,會打亂程序的執行邏輯。

以上就是本文的全部內容,希望對大家學習Java程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 清苑县| 罗江县| 漳浦县| 祁门县| 徐闻县| 元阳县| 独山县| 开封县| 区。| 长武县| 合山市| 丰镇市| 休宁县| 临清市| 崇仁县| 宝应县| 固阳县| 伽师县| 麻江县| 白玉县| SHOW| 吉林省| 库车县| 固始县| 邯郸县| 辽宁省| 碌曲县| 诸暨市| 监利县| 华宁县| 宜川县| 新晃| 丘北县| 莱阳市| 齐河县| 山西省| 金川县| 沭阳县| 阳原县| 大冶市| 金溪县|