小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Java高并發(fā)24-使用自定義鎖生成一個(gè)消費(fèi)模型

 路人甲Java 2021-04-25

一、使用自定義鎖實(shí)現(xiàn)生成--消費(fèi)模型

下面我們使用上節(jié)自定義的鎖實(shí)現(xiàn)一個(gè)簡單的生產(chǎn)--消費(fèi)模型,代碼如下:

package com.ruigege.LockSourceAnalysis6;

import java.util.Queue;
import java.util.concurrent.locks.Condition;

public class Test {
 final static NonReentrantLock lock = new NonReentrantLock();
 final static Condition notFull = lock.newCondition();
 final static Condition notEmpty = lock.newCondition();
 
 final static Queue<String> queue = new LinkedBlockingQueue<String>();
 final static int queueSize = 10;
 
 public static void main(String[] args) {
  Thread producer = new Thread(new Runnable() {
   public void run() {
    // 獲取獨(dú)占鎖
    lock.lock();
    try {
     // (1)如果隊(duì)列滿了,則等待
     while(queue.size() == queueSize) {
      notEmpty.await();
     }
     // (2)添加元素到隊(duì)列
     queue.add("ele");
     
     // (3)喚醒消費(fèi)線程
     notFull.signalAll();
    }catch(Exception e) {
     e.printStackTrace();
    }finally {
     // 釋放鎖
     lock.unlock();
    }
   }
  });
  
  Thread consumer = new Thread(new Runnable() {
   public void run() {
    // 獲取獨(dú)占鎖
    lock.lock();
    try {
     // 隊(duì)列空,則等待
     while(0 == queue.size()) {
      notFull.await();
     }
     // 消費(fèi)一個(gè)元素
     String ele = queue.poll();
     // 喚醒生產(chǎn)線程
     notEmpty.signalAll();
    }catch(Exception e) {
     e.printStackTrace();
    }finally {
     // 釋放鎖
     lock.unlock();
    }
   }
  });
  // 啟動線程
  producer.start();
  consumer.start();
 }

}

  • 如上代碼首先創(chuàng)建了一個(gè)NonReentrantLock的一個(gè)對象lock,然后調(diào)用lock.newCondition創(chuàng)建了兩個(gè)條件變量,用來進(jìn)行生產(chǎn)者和消費(fèi)者線程之間的同步。
  • 在main函數(shù)中,首先創(chuàng)建了producer生產(chǎn)線程,在線程內(nèi)部首先調(diào)用lock.lock()獲取獨(dú)占鎖,然后判斷當(dāng)前隊(duì)列是否已經(jīng)滿了,如果滿了則調(diào)用notEmpty.await()阻塞掛起當(dāng)前線程,需要注意的是,這里使用了while而不是if是為了避免虛假喚醒,如果隊(duì)列不滿則直接向隊(duì)列里面添加元素,然后調(diào)用notFull.signalAll()喚醒所有因?yàn)橄M(fèi)元素而被i阻塞的消費(fèi)線程,最后釋放獲取的鎖。

二.使用自定義鎖實(shí)現(xiàn)一個(gè)消費(fèi)模型

package com.ruigege.LockSourceAnalysis6;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class NonReentrantLockME implements Lock,java.io.Serializable{
 // 內(nèi)部幫助類
 private static class Sync extends AbstractQueueSynchronizer {
  // 是否鎖已經(jīng)被持有
  protected boolean isHeldExclusively() {
   return getState() == 1;
  }
  
  // 如果state為0,則嘗試獲取鎖
  public boolean tryAcquire(int acquires) {
   assert acquires == 1;
   if(compareAndSetState(0,1)) {
    setExclusiveOwnerThread(Thread.currentThread());
    return true;
   }
   return false;
  }
  
  // 嘗試釋放鎖,設(shè)置state為0
  protected boolean tryRelease(int release) {
   assert releases == 1;
   if(getState() == 0) {
    throw new IllegalMonitorStateException();
   }
   setExclusiveOwnerThread(null);
   setState(0);
   return true;
  }
  
  // 提供條件變量接口
  Condition newConditon() {
   return new ConditionObject();
  }
 }
 
 // 創(chuàng)建一個(gè)Sync來做具體的工作
 private final Sync sync = new Sync();
 
 public void lock() {
  sync.acquire(1);
 }
 
 public boolean tryLock() {
  return sync.tryAcquire(1);
 }
 
 public void unlock() {
  sync.release(1);
  
 }
 public Condition newCondition() {
  return sync.newConditon();
 }
 
 
 public boolean isLocked() {
  return sync.isHeldExclusively();
 }
 
 public void lockInterruptibly() throws InterruptedException {
  sync.acquireInterruptibly(1);
 }

 public boolean tryLock(long timeout,TimeUnit unit) throws InterruptedException {
  return sync.tryAcquireNanos(1,unit.toNanos(timeout));
 }
}

  • 使用NonReentrantLock創(chuàng)建一個(gè)實(shí)例,然后調(diào)用newCondition方法來生成兩個(gè)條件變量來進(jìn)行生產(chǎn)者和消費(fèi)者線程之間的同步。
  • 在main函數(shù)中,首先創(chuàng)建了producer生產(chǎn)線程,在線程內(nèi)部先獲取了獨(dú)占鎖,然后看一下隊(duì)列是否滿了,如果滿了,那就阻塞當(dāng)前線程,如果沒有滿直接在隊(duì)列中加入隊(duì)列中,這里使用的while循環(huán)而不是使用if語句,這是為了避免虛假喚醒。然后調(diào)用notFull.sinalAll()喚醒所有因?yàn)橄M(fèi)元素而被阻塞的消費(fèi)線程,最后釋放了鎖。
  • 在main函數(shù)中創(chuàng)建了consumer線程,先獲取獨(dú)占鎖,先判斷隊(duì)列有沒有元素,如果沒有元素,那么就先掛起當(dāng)前線程,這里使用了while是為了避免虛假喚醒,如果隊(duì)列中不為空,那么就拿出一個(gè)元素,然后喚醒因?yàn)殛?duì)列滿而被阻塞的生產(chǎn)線程,最后釋放獲取的鎖。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多