jdk鎖的使用
ReentrantLock
public class JdkLockTest implements Runnable{ private ReentrantLock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); private static int i = 0; public static void main(String[] args) { JdkLockTest jdkLockTest = new JdkLockTest(); Thread t1 = new Thread(jdkLockTest); Thread t2 = new Thread(jdkLockTest); Thread t3 = new Thread(jdkLockTest); t1.start(); t2.start(); t3.start(); } @Override public void run(){ lock .lock(); try { System.out.println("開始等待2s"); condition.await(2, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("ThreadName=" + Thread.currentThread().getName()); for(int j=0; j<1000000; j++){ i++; } System.out.println("i = " + i); lock.unlock(); } }
ReentrantLock其他方法
- getHoldCount() 查詢當前執行緒保持此鎖的次數,也就是執行此執行緒執行lock方法的次數
- getQueueLength()返回正等待獲取此鎖的執行緒估計數,比如啟動10個執行緒,1個執行緒獲得鎖,此時返回的是9
- getWaitQueueLength(Condition condition)返回等待與此鎖相關的給定條件的執行緒估計數。比如10個執行緒,用同一個condition物件,並且此時這10個執行緒都執行了condition物件的await方法,那麼此時執行此方法返回10
- hasWaiters(Condition condition)查詢是否有執行緒等待與此鎖有關的給定條件(condition),對於指定contidion物件,有多少執行緒執行了condition.await方法
- hasQueuedThread(Thread thread)查詢給定執行緒是否等待獲取此鎖
- hasQueuedThreads()是否有執行緒等待此鎖
- isFair()該鎖是否公平鎖
- isHeldByCurrentThread() 當前執行緒是否保持鎖鎖定,執行緒的執行lock方法的前後分別是false和true
- isLock()此鎖是否有任意執行緒佔用
- lockInterruptibly()如果當前執行緒未被中斷,獲取鎖
- tryLock()嘗試獲得鎖,僅在呼叫時鎖未被執行緒佔用,獲得鎖
- tryLock(long timeout TimeUnit unit)如果鎖在給定等待時間內沒有被另一個執行緒保持,則獲取該鎖
Semaphore
public class SemaphoreTest {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
ExecutorService executorService = Executors.newFixedThreadPool(10);
for(int i=0; i<10; i++){
executorService.execute(new Test(semaphore));
}
executorService.shutdown();
}
}
class Test implements Runnable{
private Semaphore semaphore;
private int i=0;
public Test(){}
public Test(Semaphore semaphore){
this.semaphore = semaphore;
}
@Override
public void run() {
try {
semaphore.acquire();
for(int j=0; j<1000000; j++){
i++;
}
System.out.println("i = " + i);
System.out.println("當前執行緒=====》"+ Thread.currentThread().getName());
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
其他方法,(摘自網路)
Semaphore的方法如下:
——Semaphore(permits) 初始化許可證數量的建構函式
——Semaphore(permits,fair) 初始化許可證數量和是否公平模式的建構函式
——isFair() 是否公平模式FIFO
——availablePermits() 獲取當前可用的許可證數量
——acquire()
當前執行緒嘗試去阻塞的獲取1個許可證。
此過程是阻塞的,它會一直等待許可證,直到發生以下任意一件事:
當前執行緒獲取了1個可用的許可證,則會停止等待,繼續執行。
當前執行緒被中斷,則會丟擲InterruptedException異常,並停止等待,繼續執行。
——acquire(permits)
當前執行緒嘗試去阻塞的獲取permits個許可證。
此過程是阻塞的,它會一直等待許可證,直到發生以下任意一件事:
當前執行緒獲取了n個可用的許可證,則會停止等待,繼續執行。
當前執行緒被中斷,則會丟擲InterruptedException異常,並停止等待,繼續執行。
——acquierUninterruptibly()
當前執行緒嘗試去阻塞的獲取1個許可證(不可中斷的)。
此過程是阻塞的,它會一直等待許可證,直到發生以下任意一件事:
當前執行緒獲取了1個可用的許可證,則會停止等待,繼續執行。
——acquireUninterruptibly(permits)
當前執行緒嘗試去阻塞的獲取permits個許可證。
此過程是阻塞的,它會一直等待許可證,直到發生以下任意一件事:
當前執行緒獲取了n個可用的許可證,則會停止等待,繼續執行。
——tryAcquire()
當前執行緒嘗試去獲取1個許可證。
此過程是非阻塞的,它只是在方法呼叫時進行一次嘗試。
如果當前執行緒獲取了1個可用的許可證,則會停止等待,繼續執行,並返回true。
如果當前執行緒沒有獲得這個許可證,也會停止等待,繼續執行,並返回false。
——tryAcquire(permits)
當前執行緒嘗試去獲取permits個許可證。
此過程是非阻塞的,它只是在方法呼叫時進行一次嘗試。
如果當前執行緒獲取了permits個可用的許可證,則會停止等待,繼續執行,並返回true。
如果當前執行緒沒有獲得permits個許可證,也會停止等待,繼續執行,並返回false。
——tryAcquire(timeout,TimeUnit)
當前執行緒在限定時間內,阻塞的嘗試去獲取1個許可證。
此過程是阻塞的,它會一直等待許可證,直到發生以下任意一件事:
當前執行緒獲取了可用的許可證,則會停止等待,繼續執行,並返回true。
當前執行緒等待時間timeout超時,則會停止等待,繼續執行,並返回false。
當前執行緒在timeout時間內被中斷,則會丟擲InterruptedException一次,並停止等待,繼續執行。
——tryAcquire(permits,timeout,TimeUnit)
當前執行緒在限定時間內,阻塞的嘗試去獲取permits個許可證。
此過程是阻塞的,它會一直等待許可證,直到發生以下任意一件事:
當前執行緒獲取了可用的permits個許可證,則會停止等待,繼續執行,並返回true。
當前執行緒等待時間timeout超時,則會停止等待,繼續執行,並返回false。
當前執行緒在timeout時間內被中斷,則會丟擲InterruptedException一次,並停止等待,繼續執行。
——release() 當前執行緒釋放1個可用的許可證。
——release(permits) 當前執行緒釋放permits個可用的許可證。
——drainPermits() 當前執行緒獲得剩餘的所有可用許可證。
——hasQueuedThreads() 判斷當前Semaphore物件上是否存在正在等待許可證的執行緒。
——getQueueLength() 獲取當前Semaphore物件上是正在等待許可證的執行緒數量。
ReadWriteLock 當寫操作時,其他執行緒無法讀取或寫入資料,而當讀操作時,其它執行緒無法寫入資料,但卻可以讀取資料 。
public class ReadWriteLockTest { public static void main(String[] args) { TestReadWrite testReadWrite = new TestReadWrite(); for(int i=0; i<10; i++){ new Thread(testReadWrite::read).start(); } for(int j=0; j<10; j++) { new Thread(() -> testReadWrite.write("你好")).start(); } } } class TestReadWrite{ private String data; private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); public void read(){ readWriteLock.readLock().lock();//執行緒只能讀,不能寫 System.out.println(Thread.currentThread().getName() + "讀取資料========"); try { Thread.sleep((long)(Math.random()*1000)); System.out.println(Thread.currentThread().getName() + "讀取完資料 :" + data); } catch (InterruptedException e) { e.printStackTrace(); } finally { readWriteLock.readLock().unlock(); } } public void write(String data){ readWriteLock.writeLock().lock();//不允許其他執行緒讀寫操作 System.out.println(Thread.currentThread().getName() + "寫資料========"); try { Thread.sleep((long) (Math.random() * 1000)); this.data = data; System.out.println(Thread.currentThread().getName() + "寫資料完成 ==" + data); } catch (InterruptedException e) { e.printStackTrace(); } finally { readWriteLock.writeLock().unlock(); } } }
CountDownLacth
某一執行緒在開始執行前等待n個執行緒執行完畢。將CountDownLatch的計數器初始化為n new CountDownLatch(n)
,每當一個任務執行緒執行完畢,就將計數器減1 countdownlatch.countDown()
,當計數器的值變為0時,在CountDownLatch上 await()
的執行緒就會被喚醒。
public class CountDownLacthTest { public static void main(String[] args) { final CountDownLatch countDown = new CountDownLatch(2); Thread t1 = new Thread(() -> { System.out.println("執行緒t1開始執行-------------"); try { System.out.println("執行緒t1等待其他執行緒-------------"); countDown.await(); System.out.println("執行緒t1繼續執行-------------"); } catch (InterruptedException e) { e.printStackTrace(); } },"t1"); Thread t2 = new Thread(() -> { try { System.out.println("執行緒t2開始執行-------------"); Thread.sleep((long) (Math.random()*1000)); System.out.println("執行緒t2執行完畢-------------"); countDown.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } },"t2"); Thread t3 = new Thread(() -> { try { System.out.println("執行緒t3開始執行-------------"); Thread.sleep((long) (Math.random()*1000)); System.out.println("執行緒t3執行完畢-------------"); countDown.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } },"t3"); t1.start(); t2.start(); t3.start(); } }
CyclicBarrier 注意:當執行緒數和parties不一致的時候有可能發生阻塞問題!最後剩下的執行緒數不足parties,無法繼續執行下去
public class CyclicBarrierTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CyclicBarrier cb = new CyclicBarrier(3);//當有3個執行緒到達時,共同執行 //final CyclicBarrier cb = new CyclicBarrier(3, () -> System.out.println("********我最先執行***********")); for (int i = 0; i < 3; i++) { Runnable runnable = () -> { try { Thread.sleep((long) (Math.random() * 1000)); System.out.println("執行緒" + Thread.currentThread().getName() + "即將到達集合地點1,當前已有" + cb.getNumberWaiting() + "個已經到達,正在等候"); cb.await();//到此如果沒有達到公共屏障點,則該執行緒處於等待狀態,如果達到公共屏障點則所有處於等待的執行緒都繼續往下執行 Thread.sleep((long) (Math.random() * 1000)); System.out.println("執行緒" + Thread.currentThread().getName() + "即將到達集合地點2,當前已有" + cb.getNumberWaiting() + "個已經到達,正在等候"); cb.await(); Thread.sleep((long) (Math.random() * 1000)); System.out.println("執行緒" + Thread.currentThread().getName() + "即將到達集合地點3,當前已有" + cb.getNumberWaiting() + "個已經到達,正在等候"); cb.await(); } catch (Exception e) { e.printStackTrace(); } }; service.execute(runnable); } service.shutdown(); } }