首頁 > 軟體

各種同步控制工具的使用

2020-06-16 17:13:46

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

概述

ReadWriteLockJDK5中提供的寫分離

-不互斥:讀讀不阻塞。
-寫互斥:阻塞寫,寫也會阻塞
-寫互斥:寫寫阻塞。

主要使用

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的時序問題

本文永久更新連結地址http://www.linuxidc.com/Linux/2017-05/144287.htm


IT145.com E-mail:sddin#qq.com