/**
* 1,ReentrantLock和synchronized都是可重入鎖,Reentrant的本意就是“可重入的”。可重入鎖顧名思義,就是在擁有鎖的情況下可以調用其它需要本鎖的方法或者代碼塊
* (同一個鎖對象)
*,2,synchronized只能實現非公平鎖,ReentrantLock可以實現公平鎖和非公平鎖。公平鎖或者非公平鎖,顧名思義就是線程獲取鎖的順序是否和加鎖的順序一致。ReentrantLock
* 默認的構造方法創建的是非公平鎖,ReentrantLock(true)創建的是公平鎖。因爲公平鎖是將線程放到一個隊列裏面按次序進行調度(FIFO),因此性能比較低。
* 3,ReentrantLock的鎖必須手動釋放,即調用unlock()方法釋放鎖,否則一直阻塞。釋放鎖的代碼最好在finally代碼塊中進行,因爲ReentrantLock發生異常時不會釋放鎖,而synchronized
* 修飾的代碼塊發生異常時可以釋放鎖。
* 4,synchronized與wait()/notify()、notifyAll()方法相結合可以實現線程間的通信。ReentrantLock和Condition配合能實現類似的功能,並且功能更強大。
* ReentrantLock和Condition的組合可以喚醒某個特定的線程,而synchronized喚醒哪個線程,是不確定的。
* 5,synchronized鎖對象的wait()方法相當於Condition的await()方法,會釋放鎖,線程進入阻塞狀態。
* synchronized鎖對象的wait(long)方法相當於Condition類的await(long)方法,多少秒之後才進入阻塞狀態並釋放鎖。
* synchronized鎖對類的notify()方法相當於Condition的signal()方法,notifyAll()方法相當於Condition類的signalAll()方法,喚醒等待的線程
* 6,參考博客:https://www.cnblogs.com/qlqwjy/p/10130454.html,感謝作者
*
*/
public class ReentrantLockTest {
List<Integer> list=new ArrayList<Integer>();
//創建鎖
private Lock lock=new ReentrantLock();
private Condition consumerCd = lock.newCondition();
private Condition producterCd = lock.newCondition();
/**
* 創建兩個消費者線程,兩個生產者線程
*/
public void f1() {
Thread consumer1=new Thread(new Runnable() {
@Override
public void run() {
consumeMethod();
}
},"消費者1");
Thread consumer2=new Thread(new Runnable() {
@Override
public void run() {
consumeMethod();
}
},"消費者2");
Thread producter1=new Thread(new Runnable() {
@Override
public void run() {
productMethod();
}
},"生產者1");
Thread producter2=new Thread(new Runnable() {
@Override
public void run() {
productMethod();
}
},"生產者2");
consumer1.start();
consumer2.start();
producter1.start();
producter2.start();
}
/**
* 消費方法
* 如果數組長度大於0,則消費者線程消費一個元素。否則給生產者線程發信號喚醒生產者進行生產,自己等待。
*/
public void consumeMethod(){
try {
lock.lock();
while(true){
if(list.size()>0){
System.out.println(Thread.currentThread().getName()+"消費了一個產品:"+list.get(0));
list.remove(0);
}else{
//signal()方法要在await()方法之前執行,因爲await()方法是阻塞的,一旦await()方法先執行,signal()方法就不能及時執行。
producterCd.signal();
consumerCd.await();
}
}
} catch (Exception e) {
}finally{
lock.unlock();
}
}
/**
* 生產方法
* 如果數組長度等於0,生產者線程則生產一個元素,並給消費者線程發信號喚醒消費者進行消費,自己等待
*/
public void productMethod(){
try {
lock.lock();
Random random=new Random();
while(true){
if(list.size()==0){
int value=random.nextInt(100);
list.add(value);
System.out.println(Thread.currentThread().getName()+"生產了一個產品:"+value);
consumerCd.signal();
}else{
producterCd.await();
}
}
} catch (Exception e) {
}finally{
lock.unlock();
}
}
public static void main(String[] args) {
ReentrantLockTest reentrantLockTest=new ReentrantLockTest();
reentrantLockTest.f1();
}
}
控制檯輸出(部分數據):
生產者2生產了一個產品:61
消費者1消費了一個產品:61
生產者1生產了一個產品:27
消費者2消費了一個產品:27
生產者2生產了一個產品:41
消費者1消費了一個產品:41
生產者1生產了一個產品:33
消費者2消費了一個產品:33
生產者2生產了一個產品:40
消費者1消費了一個產品:40
生產者1生產了一個產品:43
消費者2消費了一個產品:43
生產者2生產了一個產品:47
消費者1消費了一個產品:47
生產者1生產了一個產品:85
消費者2消費了一個產品:85
生產者2生產了一個產品:13
消費者1消費了一個產品:13
生產者1生產了一個產品:66
消費者2消費了一個產品:66
生產者2生產了一個產品:98
消費者1消費了一個產品:98
生產者1生產了一個產品:91
消費者2消費了一個產品:91
生產者2生產了一個產品:72
消費者1消費了一個產品:72
生產者1生產了一個產品:11
消費者2消費了一個產品:11
生產者2生產了一個產品:91
消費者1消費了一個產品:91
生產者1生產了一個產品:78
消費者2消費了一個產品:78
生產者2生產了一個產品:25
消費者1消費了一個產品:25
生產者1生產了一個產品:5
消費者2消費了一個產品:5
生產者2生產了一個產品:6
消費者1消費了一個產品:6
生產者1生產了一個產品:20
消費者2消費了一個產品:20
生產者2生產了一個產品:93
消費者1消費了一個產品:93
生產者1生產了一個產品:31
消費者2消費了一個產品:31
生產者2生產了一個產品:12
消費者1消費了一個產品:12
生產者1生產了一個產品:33
消費者2消費了一個產品:33
生產者2生產了一個產品:25
消費者1消費了一個產品:25
生產者1生產了一個產品:57
消費者2消費了一個產品:57
生產者2生產了一個產品:96
消費者1消費了一個產品:96
生產者1生產了一個產品:9
消費者2消費了一個產品:9
生產者2生產了一個產品:87
消費者1消費了一個產品:87
生產者1生產了一個產品:48
消費者2消費了一個產品:48
生產者2生產了一個產品:41
消費者1消費了一個產品:41
生產者1生產了一個產品:62
消費者2消費了一個產品:62
生產者2生產了一個產品:4
消費者1消費了一個產品:4
生產者1生產了一個產品:63
聲明:隨手一寫,並不嚴謹,切勿作爲參考