真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

深入淺析Java中的Condition條件

深入淺析Java中的Condition條件?針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

在南溪等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站建設(shè)、網(wǎng)站制作 網(wǎng)站設(shè)計(jì)制作按需求定制開發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),網(wǎng)絡(luò)營(yíng)銷推廣,外貿(mào)網(wǎng)站制作,南溪網(wǎng)站建設(shè)費(fèi)用合理。

Condition介紹

Condition的作用是對(duì)鎖進(jìn)行更精確的控制。Condition中的await()方法相當(dāng)于Object的wait()方法,Condition中的signal()方法相當(dāng)于Object的notify()方法,Condition中的signalAll()相當(dāng)于Object的notifyAll()方法。不同的是,Object中的wait(),notify(),notifyAll()方法是和"同步鎖"(synchronized關(guān)鍵字)捆綁使用的;而Condition是需要與"互斥鎖"/"共享鎖"捆綁使用的。

Condition函數(shù)列表

// 造成當(dāng)前線程在接到信號(hào)或被中斷之前一直處于等待狀態(tài)。
void await()
// 造成當(dāng)前線程在接到信號(hào)、被中斷或到達(dá)指定等待時(shí)間之前一直處于等待狀態(tài)。
boolean await(long time, TimeUnit unit)
// 造成當(dāng)前線程在接到信號(hào)、被中斷或到達(dá)指定等待時(shí)間之前一直處于等待狀態(tài)。
long awaitNanos(long nanosTimeout)
// 造成當(dāng)前線程在接到信號(hào)之前一直處于等待狀態(tài)。
void awaitUninterruptibly()
// 造成當(dāng)前線程在接到信號(hào)、被中斷或到達(dá)指定最后期限之前一直處于等待狀態(tài)。
boolean awaitUntil(Date deadline)
// 喚醒一個(gè)等待線程。
void signal()
// 喚醒所有等待線程。
void signalAll()

Condition示例

示例1是通過Object的wait(), notify()來演示線程的休眠/喚醒功能。

示例2是通過Condition的await(), signal()來演示線程的休眠/喚醒功能。

示例3是通過Condition的高級(jí)功能。

示例1

public class WaitTest1 {
  public static void main(String[] args) {
    ThreadA ta = new ThreadA("ta");
    synchronized(ta) { // 通過synchronized(ta)獲取“對(duì)象ta的同步鎖”
      try {
        System.out.println(Thread.currentThread().getName()+" start ta");
        ta.start();
        System.out.println(Thread.currentThread().getName()+" block");
        ta.wait();  // 等待
        System.out.println(Thread.currentThread().getName()+" continue");
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
  static class ThreadA extends Thread{
    public ThreadA(String name) {
      super(name);
    }
    public void run() {
      synchronized (this) { // 通過synchronized(this)獲取“當(dāng)前對(duì)象的同步鎖”
        System.out.println(Thread.currentThread().getName()+" wakup others");
        notify();  // 喚醒“當(dāng)前對(duì)象上的等待線程”
      }
    }
  }
}

示例2

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionTest1 {
  private static Lock lock = new ReentrantLock();
  private static Condition condition = lock.newCondition();
  public static void main(String[] args) {
    ThreadA ta = new ThreadA("ta");
    lock.lock(); // 獲取鎖
    try {
      System.out.println(Thread.currentThread().getName()+" start ta");
      ta.start();
      System.out.println(Thread.currentThread().getName()+" block");
      condition.await();  // 等待
      System.out.println(Thread.currentThread().getName()+" continue");
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      lock.unlock();  // 釋放鎖
    }
  }
  static class ThreadA extends Thread{
    public ThreadA(String name) {
      super(name);
    }
    public void run() {
      lock.lock();  // 獲取鎖
      try {
        System.out.println(Thread.currentThread().getName()+" wakup others");
        condition.signal();  // 喚醒“condition所在鎖上的其它線程”
      } finally {
        lock.unlock();  // 釋放鎖
      }
    }
  }
}

運(yùn)行結(jié)果:

main start ta
main block
ta wakup others
main continue

通過“示例1”和“示例2”,我們知道Condition和Object的方法有一下對(duì)應(yīng)關(guān)系:

              Object      Condition 
休眠          wait        await
喚醒個(gè)線程     notify      signal
喚醒所有線程   notifyAll   signalAll

Condition除了支持上面的功能之外,它更強(qiáng)大的地方在于:能夠更加精細(xì)的控制多線程的休眠與喚醒。對(duì)于同一個(gè)鎖,我們可以創(chuàng)建多個(gè)Condition,在不同的情況下使用不同的Condition。

例如,假如多線程讀/寫同一個(gè)緩沖區(qū):當(dāng)向緩沖區(qū)中寫入數(shù)據(jù)之后,喚醒"讀線程";當(dāng)從緩沖區(qū)讀出數(shù)據(jù)之后,喚醒"寫線程";并且當(dāng)緩沖區(qū)滿的時(shí)候,"寫線程"需要等待;當(dāng)緩沖區(qū)為空時(shí),"讀線程"需要等待。         如果采用Object類中的wait(), notify(), notifyAll()實(shí)現(xiàn)該緩沖區(qū),當(dāng)向緩沖區(qū)寫入數(shù)據(jù)之后需要喚醒"讀線程"時(shí),不可能通過notify()或notifyAll()明確的指定喚醒"讀線程",而只能通過notifyAll喚醒所有線程(但是notifyAll無法區(qū)分喚醒的線程是讀線程,還是寫線程)。  但是,通過Condition,就能明確的指定喚醒讀線程。

看看下面的示例3,可能對(duì)這個(gè)概念有更深刻的理解。 

示例3

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class BoundedBuffer {
  final Lock lock = new ReentrantLock();
  final Condition notFull = lock.newCondition(); 
  final Condition notEmpty = lock.newCondition(); 
  final Object[] items = new Object[5];
  int putptr, takeptr, count;
  public void put(Object x) throws InterruptedException {
    lock.lock();  //獲取鎖
    try {
      // 如果“緩沖已滿”,則等待;直到“緩沖”不是滿的,才將x添加到緩沖中。
      while (count == items.length)
        notFull.await();
      // 將x添加到緩沖中
      items[putptr] = x; 
      // 將“put統(tǒng)計(jì)數(shù)putptr+1”;如果“緩沖已滿”,則設(shè)putptr為0。
      if (++putptr == items.length) putptr = 0;
      // 將“緩沖”數(shù)量+1
      ++count;
      // 喚醒take線程,因?yàn)閠ake線程通過notEmpty.await()等待
      notEmpty.signal();
      // 打印寫入的數(shù)據(jù)
      System.out.println(Thread.currentThread().getName() + " put "+ (Integer)x);
    } finally {
      lock.unlock();  // 釋放鎖
    }
  }
  public Object take() throws InterruptedException {
    lock.lock();  //獲取鎖
    try {
      // 如果“緩沖為空”,則等待;直到“緩沖”不為空,才將x從緩沖中取出。
      while (count == 0) 
        notEmpty.await();
      // 將x從緩沖中取出
      Object x = items[takeptr]; 
      // 將“take統(tǒng)計(jì)數(shù)takeptr+1”;如果“緩沖為空”,則設(shè)takeptr為0。
      if (++takeptr == items.length) takeptr = 0;
      // 將“緩沖”數(shù)量-1
      --count;
      // 喚醒put線程,因?yàn)閜ut線程通過notFull.await()等待
      notFull.signal();
      // 打印取出的數(shù)據(jù)
      System.out.println(Thread.currentThread().getName() + " take "+ (Integer)x);
      return x;
    } finally {
      lock.unlock();  // 釋放鎖
    }
  } 
}
public class ConditionTest2 {
  private static BoundedBuffer bb = new BoundedBuffer();
  public static void main(String[] args) {
    // 啟動(dòng)10個(gè)“寫線程”,向BoundedBuffer中不斷的寫數(shù)據(jù)(寫入0-9);
    // 啟動(dòng)10個(gè)“讀線程”,從BoundedBuffer中不斷的讀數(shù)據(jù)。
    for (int i=0; i<10; i++) {
      new PutThread("p"+i, i).start();
      new TakeThread("t"+i).start();
    }
  }
  static class PutThread extends Thread {
    private int num;
    public PutThread(String name, int num) {
      super(name);
      this.num = num;
    }
    public void run() {
      try {
        Thread.sleep(1);  // 線程休眠1ms
        bb.put(num);    // 向BoundedBuffer中寫入數(shù)據(jù)
      } catch (InterruptedException e) {
      }
    }
  }
  static class TakeThread extends Thread {
    public TakeThread(String name) {
      super(name);
    }
    public void run() {
      try {
        Thread.sleep(10);          // 線程休眠1ms
        Integer num = (Integer)bb.take();  // 從BoundedBuffer中取出數(shù)據(jù)
      } catch (InterruptedException e) {
      }
    }
  }
}

(某一次)運(yùn)行結(jié)果:

p1 put  1
p4 put  4
p5 put  5
p0 put  0
p2 put  2
t0 take 1
p3 put  3
t1 take 4
p6 put  6
t2 take 5
p7 put  7
t3 take 0
p8 put  8
t4 take 2
p9 put  9
t5 take 3
t6 take 6
t7 take 7
t8 take 8
t9 take 9

結(jié)果說明:

(01) BoundedBuffer 是容量為5的緩沖,緩沖中存儲(chǔ)的是Object對(duì)象,支持多線程的讀/寫緩沖。多個(gè)線程操作“一個(gè)BoundedBuffer對(duì)象”時(shí),它們通過互斥鎖lock對(duì)緩沖區(qū)items進(jìn)行互斥訪問;而且同一個(gè)BoundedBuffer對(duì)象下的全部線程共用“notFull”和“notEmpty”這兩個(gè)Condition。

       notFull用于控制寫緩沖,notEmpty用于控制讀緩沖。當(dāng)緩沖已滿的時(shí)候,調(diào)用put的線程會(huì)執(zhí)行notFull.await()進(jìn)行等待;當(dāng)緩沖區(qū)不是滿的狀態(tài)時(shí),就將對(duì)象添加到緩沖區(qū)并將緩沖區(qū)的容量count+1,最后,調(diào)用notEmpty.signal()緩沖notEmpty上的等待線程(調(diào)用notEmpty.await的線程)。 簡(jiǎn)言之,notFull控制“緩沖區(qū)的寫入”,當(dāng)往緩沖區(qū)寫入數(shù)據(jù)之后會(huì)喚醒notEmpty上的等待線程。

       同理,notEmpty控制“緩沖區(qū)的讀取”,當(dāng)讀取了緩沖區(qū)數(shù)據(jù)之后會(huì)喚醒notFull上的等待線程。

(02) 在ConditionTest2的main函數(shù)中,啟動(dòng)10個(gè)“寫線程”,向BoundedBuffer中不斷的寫數(shù)據(jù)(寫入0-9);同時(shí),也啟動(dòng)10個(gè)“讀線程”,從BoundedBuffer中不斷的讀數(shù)據(jù)。

(03) 簡(jiǎn)單分析一下運(yùn)行結(jié)果。

     1, p1線程向緩沖中寫入1。    此時(shí),緩沖區(qū)數(shù)據(jù):   | 1 |   |   |   |   |

     2, p4線程向緩沖中寫入4。    此時(shí),緩沖區(qū)數(shù)據(jù):   | 1 | 4 |   |   |   |

     3, p5線程向緩沖中寫入5。    此時(shí),緩沖區(qū)數(shù)據(jù):   | 1 | 4 | 5 |   |   |

     4, p0線程向緩沖中寫入0。    此時(shí),緩沖區(qū)數(shù)據(jù):   | 1 | 4 | 5 | 0 |   |

     5, p2線程向緩沖中寫入2。    此時(shí),緩沖區(qū)數(shù)據(jù):   | 1 | 4 | 5 | 0 | 2 |

     此時(shí),緩沖區(qū)容量為5;緩沖區(qū)已滿!如果此時(shí),還有“寫線程”想往緩沖中寫入數(shù)據(jù),會(huì)調(diào)用put中的notFull.await()等待,直接緩沖區(qū)非滿狀態(tài),才能繼續(xù)運(yùn)行。

     6, t0線程從緩沖中取出數(shù)據(jù)1。此時(shí),緩沖區(qū)數(shù)據(jù):   |   | 4 | 5 | 0 | 2 |

     7, p3線程向緩沖中寫入3。    此時(shí),緩沖區(qū)數(shù)據(jù):   | 3 | 4 | 5 | 0 | 2 |

     8, t1線程從緩沖中取出數(shù)據(jù)4。此時(shí),緩沖區(qū)數(shù)據(jù):   | 3 |   | 5 | 0 | 2 |

     9, p6線程向緩沖中寫入6。    此時(shí),緩沖區(qū)數(shù)據(jù):   | 3 | 6 | 5 | 0 | 2 |
     ...

關(guān)于深入淺析Java中的Condition條件問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。


名稱欄目:深入淺析Java中的Condition條件
本文來源:http://weahome.cn/article/pedeop.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部