Lock
Lock是Java 5以後引入的新的API
- ReentrantLock
- 可保證順序、可查詢阻塞Thread list、可設置超時、查詢持有lock的Thread
- 注意必須 主動unlock,退出Thread不會清空lock
- CyclicBarrier
- 在await阻塞
- 設置阻塞 的線程數
- 從0遞增 數值
- 可以reset 數值
- 到達最大值 放行,await()的Thread
- 可break barrier,喚醒全部線程
- CountDownLatch (比CyclicBarrier少太多方法)
- 在await阻塞
- 設置 阻塞的最大數值
- 從最大值遞減
- 數值爲0放行,await()的Thread
- 不可reset 數值
- Semaphore
- 設置可用資源的最大值
- 可增 可減數值
- Exchanger
- 在exchange時阻塞,等另一個Thread調用exchange,交換Object
方法
- lock()
- lockInterruptibly()
- interrupt狀態無法獲得鎖
- 等待lock時,如果interrupt則拋異常退出
- tryLock()
- never block
- tryLock(long timeout, TimeUnit timeUnit)
- unlock()
實現類ReentrantLock
- 可以設置timeout
- 可以保證順序
- 可以查詢wait的thread 列表
Lock lock = new ReentrantLock();
lock.lock();
//critical section
lock.unlock();
ReadWriteLock
多線程讀(沒線程寫)、一個線程寫
interface
public interface ReadWriteLock {
/**
* Returns the lock used for reading.
*
* @return the lock used for reading
*/
Lock readLock();
/**
* Returns the lock used for writing.
*
* @return the lock used for writing
*/
Lock writeLock();
}
實現類 ReentrantReadWriteLock
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
readWriteLock.readLock().lock();
// multiple readers can enter this section
// if not locked for writing, and not writers waiting
// to lock for writing.
readWriteLock.readLock().unlock();
readWriteLock.writeLock().lock();
// only one writer can enter this section,
// and only if no threads are currently reading.
readWriteLock.writeLock().unlock();
CyclicBarrier
等到0通行,設置阻塞線程數量
- 設置一個 阻斷器,設置阻斷線程的數量
- 當阻斷到 指定的數量是放行
- 可以設置放行時運行的Runnable
Runnable barrier1Action = new Runnable() {
public void run() {
System.out.println("BarrierAction 1 executed ");
}
};
Runnable barrier2Action = new Runnable() {
public void run() {
System.out.println("BarrierAction 2 executed ");
}
};
CyclicBarrier barrier1 = new CyclicBarrier(2, barrier1Action);
CyclicBarrier barrier2 = new CyclicBarrier(2, barrier2Action);
CyclicBarrierRunnable barrierRunnable1 =
new CyclicBarrierRunnable(barrier1, barrier2);
CyclicBarrierRunnable barrierRunnable2 =
new CyclicBarrierRunnable(barrier1, barrier2);
new Thread(barrierRunnable1).start();
new Thread(barrierRunnable2).start();
public class CyclicBarrierRunnable implements ++Runnable++{
CyclicBarrier barrier1 = null;
CyclicBarrier barrier2 = null;
public CyclicBarrierRunnable(
CyclicBarrier barrier1,
CyclicBarrier barrier2) {
this.barrier1 = barrier1;
this.barrier2 = barrier2;
}
public void run() {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() +
" waiting at barrier 1");
this.barrier1.await();
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() +
" waiting at barrier 2");
this.barrier2.await();
System.out.println(Thread.currentThread().getName() +
" done!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
CountDownLatch
倒計時鎖
- 設置初始值
- latch.await();
- latch.countDown(); 到0時放行
Semaphore
允許進入 關鍵區域的 最大線程數
Semaphore semaphore = new Semaphore(1);
//critical section
semaphore.acquire();
...
semaphore.release();
2. 兩個線程通信
- 例如在 insertData到list後,acquire調用
- 在take object from list前,調用release
- 實際上形成一個阻塞隊列