Java線程通訊詳解_java

來源:互聯網
上載者:User

線程通訊用來保證線程協調運行,一般在做線程同步的時候才需要考慮線程通訊的問題。

1、傳統的線程通訊

通常利用Objeclt類提供的三個方法:

  1. wait() 導致當前線程等待,並釋放該同步監視器的鎖定,直到其它線程調用該同步監視器的notify()或者notifyAll()方法喚醒線程。
  2. notify(),喚醒在此同步監視器上等待的線程,如果有多個會任意選擇一個喚醒
  3. notifyAll() 喚醒在此同步監視器上等待的所有線程,這些線程通過調度競爭資源後,某個線程擷取此同步監視器的鎖,然後得以運行。

這三個方法必須由同步監視器對象調用,分為兩張情況:

同步方法時,由於同步監視器為this對象,所以可以直接調用這三個方法。

樣本如下:

public class SyncMethodThreadCommunication {  static class DataWrap{    int data = 0;    boolean flag = false;        public synchronized void addThreadA(){      if (flag) {        try {          wait();        } catch (InterruptedException e) {          e.printStackTrace();        }      }             data++;      System.out.println(Thread.currentThread().getName() + " " + data);      flag = true;      notify();    }        public synchronized void addThreadB() {      if (!flag) {        try {          wait();        } catch (InterruptedException e) {          e.printStackTrace();        }      }             data++;      System.out.println(Thread.currentThread().getName() + " " + data);      flag = false;      notify();    }  }    static class ThreadA extends Thread {    private DataWrap data;        public ThreadA(DataWrap dataWrap) {      this.data = dataWrap;    }        @Override    public void run() {      for (int i = 0; i < 10; i++) {        data.addThreadA();      }    }  }    static class ThreadB extends Thread {    private DataWrap data;        public ThreadB(DataWrap dataWrap) {      this.data = dataWrap;    }        @Override    public void run() {      for (int i = 0; i < 10; i++) {        data.addThreadB();      }    }  }    public static void main(String[] args) {    //實現兩個線程輪流對資料進行加一操作    DataWrap dataWrap = new DataWrap();        new ThreadA(dataWrap).start();    new ThreadB(dataWrap).start();  }}

同步代碼塊時,需要使用監視器對象調用這三個方法。

樣本如下:

public class SyncBlockThreadComminication {  static class DataWrap{    boolean flag;    int data;  }    static class ThreadA extends Thread{    DataWrap dataWrap;        public ThreadA(DataWrap dataWrap){      this.dataWrap = dataWrap;    }        @Override    public void run() {      for(int i = 0 ; i < 10; i++) {        synchronized (dataWrap) {          if (dataWrap.flag) {            try {              dataWrap.wait();            } catch (InterruptedException e) {              e.printStackTrace();            }          }                    dataWrap.data++;          System.out.println(getName() + " " + dataWrap.data);          dataWrap.flag = true;          dataWrap.notify();        }        }    }  }    static class ThreadB extends Thread{    DataWrap dataWrap;        public ThreadB(DataWrap dataWrap){      this.dataWrap = dataWrap;    }        @Override    public void run() {      for (int i = 0; i < 10; i++) {          synchronized (dataWrap) {            if (!dataWrap.flag) {              try {                dataWrap.wait();              } catch (InterruptedException e) {                e.printStackTrace();              }            }                        dataWrap.data++;            System.out.println(getName() + " " + dataWrap.data);            dataWrap.flag = false;            dataWrap.notify();          }        }        }        }  public static void main(String[] args) {    //實現兩個線程輪流對資料進行加一操作        DataWrap dataWrap = new DataWrap();    new ThreadA(dataWrap).start();    new ThreadB(dataWrap).start();  }}

2、使用Condition控制線程通訊

當使用Lock對象保證同步時,則使用Condition對象來保證協調。

樣本如下:

import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;import com.sun.media.sound.RIFFInvalidDataException;import javafx.scene.chart.PieChart.Data;public class SyncLockThreadCommunication {  static class DataWrap {    int data;    boolean flag;        private final Lock lock = new ReentrantLock();    private final Condition condition = lock.newCondition();        public void addThreadA() {      lock.lock();      try {        if (flag) {          try {            condition.await();          } catch (InterruptedException e) {            e.printStackTrace();          }        }                data++;        System.out.println(Thread.currentThread().getName() + " " + data);        flag = true;        condition.signal();      } finally {        lock.unlock();      }    }        public void addThreadB() {      lock.lock();      try {        if (!flag) {          try {            condition.await();          } catch (InterruptedException e) {            e.printStackTrace();          }        }                data++;        System.out.println(Thread.currentThread().getName() + " " + data);        flag = false;        condition.signal();      } finally {        lock.unlock();      }    }  }    static class ThreadA extends Thread{    DataWrap dataWrap;        public ThreadA(DataWrap dataWrap) {      this.dataWrap = dataWrap;    }        @Override    public void run() {      for (int i = 0; i < 10; i++) {        dataWrap.addThreadA();      }    }  }    static class ThreadB extends Thread{    DataWrap dataWrap;        public ThreadB(DataWrap dataWrap) {      this.dataWrap = dataWrap;    }        @Override    public void run() {      for (int i = 0; i < 10; i++) {        dataWrap.addThreadB();      }    }  }    public static void main(String[] args) {    //實現兩個線程輪流對資料進行加一操作        DataWrap dataWrap = new DataWrap();    new ThreadA(dataWrap).start();    new ThreadB(dataWrap).start();  }}

其中Condition對象的await(), singal(),singalAll()分別對應wait(),notify()和notifyAll()方法。

3、使用阻塞隊列BlockingQueue控制線程通訊

BlockingQueue是Queue介面的子介面,主要用來做線程通訊使用,它具有一個特徵:當生產者線程試圖向BlockingQueue中放入元素時,如果隊列已滿,則該線程被阻塞;當消費者線程試圖從BlockingQueue中取出元素時,如果隊列已空,則該線程被阻塞。這兩個特徵分別對應兩個支援阻塞的方法,put(E e)和take()

樣本如下:

import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;public class BlockingQueueThreadComminication {  static class DataWrap{    int data;  }    static class ThreadA extends Thread{    private BlockingQueue<DataWrap> blockingQueue;        public ThreadA(BlockingQueue<DataWrap> blockingQueue, String name) {      super(name);      this.blockingQueue = blockingQueue;    }        @Override    public void run() {      for (int i = 0; i < 100; i++) {        try {          DataWrap dataWrap = blockingQueue.take();                    dataWrap.data++;          System.out.println(getName() + " " + dataWrap.data);          sleep(1000);        } catch (InterruptedException e) {          e.printStackTrace();        }      }    }  }    static class ThreadB extends Thread{    private BlockingQueue<DataWrap> blockingQueue;    private DataWrap dataWrap;        public ThreadB(BlockingQueue<DataWrap> blockingQueue, DataWrap dataWrap, String name) {      super(name);      this.blockingQueue = blockingQueue;      this.dataWrap = dataWrap;    }        @Override    public void run() {      for (int i = 0; i < 100; i++) {        try {          dataWrap.data++;          System.out.println(getName() + " " + dataWrap.data);          blockingQueue.put(dataWrap);          sleep(1000);        } catch (InterruptedException e) {          e.printStackTrace();        }      }    }  }    public static void main(String[] args) {    ///實現兩個線程輪流對資料進行加一操作        DataWrap dataWrap = new DataWrap();    BlockingQueue<DataWrap> blockingQueue = new ArrayBlockingQueue<>(1);        new ThreadA(blockingQueue, "Consumer").start();    new ThreadB(blockingQueue, dataWrap, "Producer").start();  }}

BlockingQueue共有五個實作類別:

ArrayBlockingQueue 基於數組實現的BlockingQueue隊列

LinkedBlockingQueue 基於鏈表實現的BlockingQueue隊列

PriorityBlockingQueue 中元素需實現Comparable介面,其中元素的排序是按照Comparator進行的定製排序。

SynchronousQueue 同步隊列,要求對該隊列的存取操作必須是交替進行。

DelayQueue 集合元素必須實現Delay介面,隊列中元素排序按照Delay介面方法getDelay()的傳回值進行排序。

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.