共享鎖,運行多個線程同時臨界區ide
public void acquire()
public void acquireUninterruptibly()
public boolean tryAcquire()
public boolean tryAcquire(long timeout, TimeUnit unit)
public void release()
函數
public class SemaphoreDemo { private static final int THREAD_COUNT = 3; private static ExecutorService threadPool = Executors .newFixedThreadPool(THREAD_COUNT); private static Semaphore s = new Semaphore(1); public static void main(String[] args) { for(int i=0;i<3;i++) { threadPool.execute(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName()+"start data"); Thread.sleep(2000); s.acquire(); Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+"save data"); s.release(); System.out.println(Thread.currentThread().getName()+"release data"); Thread.sleep(2000); System.out.println(Thread.currentThread().getName()+"end data"); } catch (InterruptedException e) { e.printStackTrace(); } } }); } threadPool.shutdown(); } }
最後得出一個比較有意思的結論:Semaphore 像是一個共享的屋子,這個屋子裏面只能有必定的人數,這我的數是全部人能夠看到的,甚至與release()這個方法,能夠被別的線程進行調用,ui
通常使用acquire() 與release() 這個之間的代碼只能有固定數量的線程存在,固然這種是當前線程進行獲取和釋放this
ReadWriteLock是JDK5中提供的讀寫分離鎖
spa
讀-讀不互斥:讀讀之間不阻塞。
讀-寫互斥:讀阻塞寫,寫也會阻塞讀。
寫-寫互斥:寫寫阻塞。
線程
private static ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock();
private static Lock readLock = readWriteLock.readLock();
private static Lock writeLock = readWriteLock.writeLock();
blog
這個類若是沒有寫鎖的狀況下,讀是無阻塞的,在必定程度上提升了程序的執行效率。接口
public void run() { //isRead自定義變量(判斷這個線程是讀仍是寫) if (isRead) { //獲取讀鎖 myLock.readLock().lock(); System.out.println("讀"); //釋放讀鎖 myLock.readLock().unlock(); } else { //獲取寫鎖 myLock.writeLock().lock(); //執行現金業務 System.out.println("寫"); //釋放寫鎖 myLock.writeLock().unlock(); } }
static final CountDownLatch end = new CountDownLatch(10);
end.countDown(); //這個方法是子線程做完做業以後,調用的
end.await(); //主線等待指定數量的子線程完成做業,當全部子線程完成以後,主線程自動激活執行
get
public class CountDownLatchDemo { private static CountDownLatch countDownLatch=new CountDownLatch(10); public static void main(String[] args) { for(int i=0;i<10;i++) { new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"work"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } countDownLatch.countDown(); } }).start(); } new Thread(new Runnable() { @Override public void run() { try { countDownLatch.await(); System.out.println(Thread.currentThread().getName()+"主線程start"); } catch (InterruptedException e) { e.printStackTrace(); } } },"main1").start(); } }
public class CyclicBarrierDemo { public static class Soldier implements Runnable{ private String name; private final CyclicBarrier cyclicBarrier; public Soldier(String name,CyclicBarrier c) { this.name = name; this.cyclicBarrier=c; } @Override public void run() { try{ //等待全部士兵到齊 System.out.println(name +"報道"); cyclicBarrier.await(); dowork(); //等待全部士兵完成工做 cyclicBarrier.await(); } catch (Exception e) { e.printStackTrace(); } } public void dowork() { System.out.println(name +"完成任務"); } } public static class BarrierRun implements Runnable{ boolean flag; int number; public BarrierRun(boolean flag, int number) { this.flag = flag; this.number = number; } @Override public void run() { if(!flag) { System.out.println("士兵集合完畢"); flag=true; System.out.println("開始執行任務"); } else{ System.out.println("任務完成"); } } } public static void main(String[] args) { final int N =10; CyclicBarrier barrier =new CyclicBarrier(N,new BarrierRun(false,N)); System.out.println("集合隊伍"); for(int i=0;i<N;i++) { new Thread(new Soldier("士兵"+i,barrier)).start(); } } }
每次CyclicBarrier 調用await()方法以後,都會等待全部的子線程,以後執行CyclicBarrier 的Runnable的方法it
unpark函數能夠先於park調用。好比線程B調用unpark函數,給線程A發了一個「許可」,那麼當線程A調用park時,它發現已經有「許可」了,那麼它會立刻再繼續運行。
上面已經提到,unpark函數能夠先於park調用,這個正是它們的靈活之處。
一個線程它有可能在別的線程unPark以前,或者以後,或者同時調用了park,那麼由於park的特性,它能夠不用擔憂本身的park的時序問題