多執行緒複習筆記之三【多執行緒中的Lock使用】
Lock
1、getHoldCount()
查詢當前執行緒保持此鎖鎖定的個數,也就是呼叫lock方法的次數
2、int getQueueLength
返回正等待此鎖定的執行緒估計數,例如有5個執行緒,1個執行緒首先執行await,那麼呼叫getQueueLength返回4
3、int getWaitQueueLength(Condition condition)
返回等待與次鎖定相關的給定條件Condition的執行緒估計數,例如有5個執行緒,每個執行緒都執行了同一個condition物件的await方法,則呼叫此方法返回5.
4、boolean hasQueuedThreads
查詢是否有執行緒正在等待獲取此鎖定,lock.hasQueuedThread(thread)
5、boolean hasWaiters(Condition condition)
查詢是否有執行緒正在等待與此鎖定有關的condition條件
lock.hasWaiters(condition)執行緒數是lock.getWaitQueueLength(condition)
6、isFair
判斷是否是公平鎖
7、boolean isHeldByCurrentThread
查詢當前執行緒是否保持此鎖定
8、lockInterruptibly()
如果當前執行緒未被中斷,則獲取鎖定,如果已經被中斷則丟擲異常
9、boolean tryLock()
僅在呼叫時鎖定未被另一個執行緒保持的情況下,才獲取 該鎖定。
10、boolean tryLock(long timeout,TimeUnit unit)
如果鎖定給定等待時間內沒有被另一個執行緒保持,且當前執行緒未被中斷,則獲取該鎖定,例如:
package com.fyw.thread.lock; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class ServiceMethod { public ReentrantLock lock = new ReentrantLock(); public Condition condition = lock.newCondition(); public void awaitMethod(){ try{ if(lock.tryLock(3,TimeUnit.SECONDS)){ System.out.println(Thread.currentThread().getName()+"獲得鎖的時間:"+System.currentTimeMillis()); Thread.sleep(4000); } }catch(Exception e){ e.printStackTrace(); }finally{ if(lock.isHeldByCurrentThread()){ lock.unlock(); } } } public void notifyMethod(){ try{ lock.lock(); System.out.println("有"+lock.getWaitQueueLength(condition)+"個執行緒等待condition"); condition.signal(); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } } } public static void main(String[] args) throws InterruptedException { final ServiceMethod service = new ServiceMethod(); Runnable runnable = new Runnable(){ @Override public void run() { System.out.println(Thread.currentThread().getName()+"呼叫waitMethod時間:"+System.currentTimeMillis()); service.awaitMethod(); } }; Thread threadA = new Thread(runnable); threadA.setName("A"); threadA.start(); Thread threadB = new Thread(runnable); threadB.setName("B"); threadB.start(); }
輸出:
A呼叫waitMethod時間:1544957162945
B呼叫waitMethod時間:1544957162945
A獲得鎖的時間:1544957162946
如果將sleep(4000)改成1000,輸出如下:
A呼叫waitMethod時間:1544957292643
B呼叫waitMethod時間:1544957292643
B獲得鎖的時間:1544957292643
A獲得鎖的時間:1544957293643
【使用Condition實現執行緒順序交叉執行】
package com.fyw.thread.lock.condition;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Run {
volatile private static int nextRun = 1;
private static Lock lock = new ReentrantLock();
private static Condition condition1 = lock.newCondition();
private static Condition condition2 = lock.newCondition();
private static Condition condition3 = lock.newCondition();
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable(){
@Override
public void run() {
try {
lock.lock();
while(nextRun != 1){
condition1.await();
}
for(int i=0;i<3;i++){
System.out.println("Thread1 "+(i+1));
}
nextRun = 2;
condition2.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
});
Thread thread2 = new Thread(new Runnable(){
@Override
public void run() {
try {
lock.lock();
while(nextRun != 2){
condition2.await();
}
for(int i=0;i<3;i++){
System.out.println("Thread2 "+(i+1));
}
nextRun = 3;
condition3.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
});
Thread thread3 = new Thread(new Runnable(){
@Override
public void run() {
try {
lock.lock();
while(nextRun != 3){
condition3.await();
}
for(int i=0;i<3;i++){
System.out.println("Thread3 "+(i+1));
}
nextRun = 1;
condition1.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
});
Thread[] array1 = new Thread[5];
Thread[] array2 = new Thread[5];
Thread[] array3 = new Thread[5];
for(int i=0;i<5;i++){
array1[i] = new Thread(thread1);
array2[i] = new Thread(thread2);
array3[i] = new Thread(thread3);
array1[i].start();
array2[i].start();
array3[i].start();
}
}
}
【執行結果如下】
Thread1 1
Thread1 2
Thread1 3
Thread2 1
Thread2 2
Thread2 3
Thread3 1
Thread3 2
Thread3 3
Thread1 1
Thread1 2
Thread1 3
Thread2 1
Thread2 2
Thread2 3
Thread3 1
Thread3 2
Thread3 3
Thread1 1
Thread1 2
Thread1 3
Thread2 1
Thread2 2
Thread2 3
Thread3 1
Thread3 2
Thread3 3
Thread1 1
Thread1 2
Thread1 3
Thread2 1
Thread2 2
Thread2 3
Thread3 1
Thread3 2
Thread3 3
Thread1 1
Thread1 2
Thread1 3
Thread2 1
Thread2 2
Thread2 3
Thread3 1
Thread3 2
Thread3 3
【讀寫鎖ReentrantReadWriteLock】
讀讀共享、讀寫互斥、寫寫互斥
【讀讀共享】
package com.fyw.thread.lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadReadLock {
private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public void read(){
try {
readWriteLock.readLock().lock();
System.out.println("執行緒"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"獲得read鎖");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
readWriteLock.readLock().unlock();
}
}
public static void main(String[] args) {
ReadReadLock rrl = new ReadReadLock();
ThreadA threadA = new ThreadA(rrl);
threadA.setName("A");
threadA.start();
ThreadB threadB = new ThreadB(rrl);
threadB.setName("B");
threadB.start();
}
}
【執行結果】
執行緒B並沒有等到Asleep(10000)之後再執行,而是一起執行
執行緒A在1544972110700獲得read鎖
執行緒B在1544972110701獲得read鎖
讀寫、寫寫用法同上