Semaphore
概述
共享鎖,運行多個線程同時臨界區
主要接口
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()這個方法,可以被別的線程進行調用,
一般使用acquire() 與release() 這個之間的代碼只能有固定數量的線程存在,當然這種是當前線程進行獲取和釋放
ReadWriteLock
概述
ReadWriteLock是JDK5中提供的讀寫分離鎖
讀-讀不互斥:讀讀之間不阻塞。
讀-寫互斥:讀阻塞寫,寫也會阻塞讀。
寫-寫互斥:寫寫阻塞。
主要使用
private static ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock();
private static Lock readLock = readWriteLock.readLock();
private static Lock writeLock = readWriteLock.writeLock();
這個類如果沒有寫鎖的情況下,讀是無阻塞的,在一定程度上提高了程序的執行效率。
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();
}
}
CountDownLatch
概述:

static final CountDownLatch end = new CountDownLatch(10);
end.countDown(); //這個方法是子線程作完作業之后,調用的
end.await(); //主線等待指定數量的子線程完成作業,當所有子線程完成之后,主線程自動激活執行
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();
}
}
CyclicBarrier
概述

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的方法
LockSupport
概述
unpark函數可以先於park調用。比如線程B調用unpark函數,給線程A發了一個“許可”,那么當線程A調用park時,它發現已經有“許可”了,那么它會馬上再繼續運行。
park和unpark的靈活之處
上面已經提到,unpark函數可以先於park調用,這個正是它們的靈活之處。
一個線程它有可能在別的線程unPark之前,或者之后,或者同時調用了park,那么因為park的特性,它可以不用擔心自己的park的時序問題
