JUC------03

1.1 線程通訊

1.1.1 CountDownLatch

/**
 * @Description: *讓一些線程阻塞直到另外一些線程完成一系列操做後才被喚醒。
 * <p>
 * CountDownLatch主要有兩個方法,當一個或多個線程調用await方法時,這些線程會阻塞。
 * 其它線程調用countDown方法會將計數器減1(調用countDown方法的線程不會阻塞),
 * 當計數器的值變爲0時,因await方法阻塞的線程會被喚醒,繼續執行。
 * <p>
 * 解釋:6個同窗陸續離開教室後值班同窗才能夠關門。
 * <p>
 * main主線程必需要等前面6個線程完成所有工做後,本身才能開幹
 */
public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 1; i <= 6; i++) //6個上自習的同窗,各自離開教室的時間不一致
        {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t 號同窗離開教室");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "\t****** 班長關門走人,main線程是班長");
    }


}

1.1.2 CyclicBarrier

/**
 * CyclicBarrier
 * 的字面意思是可循環(Cyclic)使用的屏障(Barrier)。它要作的事情是,
 * 讓一組線程到達一個屏障(也能夠叫同步點)時被阻塞,
 * 直到最後一個線程到達屏障時,屏障纔會開門,全部
 * 被屏障攔截的線程纔會繼續幹活。
 * 線程進入屏障經過CyclicBarrier的await()方法。
 * <p>
 * 集齊7顆龍珠就能夠召喚神龍
 */
public class CyclicBarrierDemo {

    public static void main(String[] args) {
        //CyclicBarrier(int parties, Runnable barrierAction)
        CyclicBarrier cyclicBarrier = new CyclicBarrier( 7, () -> { System.out.println("*****集齊7顆龍珠就能夠召喚神龍"); });

        for (int i = 1; i <= 7; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "\t 星龍珠被收集 ");
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }
    }
}

忽然又想到一個知識點(跑題中。。)wait 、await、sleep、notify、signal的區別:
wait----sleepnode

  • 同:
    都是線程同步時會用到的方法,使當前線程暫停運行,把運行機會交給其它線程。
    若是任何線程在等待期間被中斷都會拋出InterruptedException
    都是native方法
  • 異:
    所在類不一樣,wait()是Object超類中的方法;而sleep()是線程Thread類中的方法
    關鍵點是對鎖的保持不一樣,wait會釋放鎖;而sleep()並不釋放鎖
    喚醒方法不徹底相同,wait依靠notify或者notifyAll、中斷髮生、或者到達指定時間來喚醒;而sleep()則是到達指定的時間後被喚醒。
    使用的位置不一樣,wait只能用在同步代碼塊中,而sleep用在任何位置。
    wait----await
    這兩個長得很像。await()的實現比較複雜:
public final void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }

先說下來源,await是ConditionObject類裏面的方法,ConditionObject實現了Condition接口;而ReentrantLock裏面默認有實現newCondition()方法,新建一個條件對象。該方法就是用在ReentrantLock中根據條件來設置等待。喚醒方法也是由專門的Signal()或者Signal()來執行。另外await會致使當前線程被阻塞,會放棄鎖,這點和wait是同樣的。併發

因爲所在的超類不一樣使用場景也不一樣,wait通常用於Synchronized中,而await只能用於ReentrantLock鎖中.
notify----signal
notify使用來喚醒使用wait的線程;而signal是用來喚醒await線程。dom

1.1.3 Semaphore

/**ui

  • @Description: TODO(這裏用一句話描述這個類的做用)this

  • 在信號量上咱們定義兩種操做:線程

  • acquire(獲取) 當一個線程調用acquire操做時,它要麼經過成功獲取信號量(信號量減1),code

  • 要麼一直等下去,直到有線程釋放信號量,或超時。對象

  • release(釋放)實際上會將信號量的值加1,而後喚醒等待的線程。接口

  • 信號量主要用於兩個目的,一個是用於多個共享資源的互斥使用,另外一個用於併發線程數的控制。
    */
    public class SemaphoreDemo {
    public static void main(String[] args) {
    Semaphore semaphore = new Semaphore(3);//模擬3個停車位ip

    for (int i = 1; i <= 6; i++) //模擬6部汽車
     {
         new Thread(() -> {
             try {
                 semaphore.acquire();
                 System.out.println(Thread.currentThread().getName() + "\t 搶到了車位");
                 TimeUnit.SECONDS.sleep(new Random().nextInt(5));
                 System.out.println(Thread.currentThread().getName() + "\t ----離開了車位");
             } catch (InterruptedException e) {
                 e.printStackTrace();
             } finally {
                 semaphore.release();
             }
         }, String.valueOf(i)).start();
     }

    } }

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息