JAVA線程14 - 新特性:同步工具

1、Semaphore

1. 簡介

Semaphore實現信號量。 java

Semaphore能夠維護當前訪問自身的線程個數,並提供了同步機制。使用Semaphore能夠控制同時訪問資源的線程個數。例如:實現一個文件容許的併發訪問數。 併發

單個信號量的Semaphore對象能夠實現互斥鎖的功能,而且能夠是由一個線程得到了鎖,再由另外一個線程釋放鎖。這可應用於死鎖恢復的一些場合。 dom

2. 示例

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {

    public static void main(String[] args) {
        ExecutorService es = Executors.newCachedThreadPool();
        final Semaphore sp = new Semaphore(3);
        for (int i = 0; i < 10; i++) {
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    try {
                        sp.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("線程"+Thread.currentThread().getName()+"進入,當前已有併發"+(3-sp.availablePermits()));
                    try {
                        Thread.sleep(new Random().nextInt(10000));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("線程"+Thread.currentThread().getName()+"即將離開");
                    sp.release();
                    System.out.println("線程"+Thread.currentThread().getName()+"已離開,當前已有併發"+(3-sp.availablePermits()));
                }
            };
            es.execute(r);
        }
        es.shutdown();
    }
}

2、CyclicBarrier

1. 簡介

障礙器。表示你們彼此等待,你們集合好後纔開始出發,分散活動後又在指定地點集合碰面。 ide

2. 示例

import java.util.Date;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CyclicBarrierTest {

    public static void main(String[] args) {
        ExecutorService es = Executors.newCachedThreadPool();
        final CyclicBarrier cb = new CyclicBarrier(5);
        for (int i = 0; i < 5; i++) {
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(new Random().nextInt(10000));
                        System.out.println(new Date()+":線程"+Thread.currentThread().getName()+"到達目的地1,當前已到達"+(cb.getNumberWaiting()+1)+",正在等候");
                        cb.await();
                        System.out.println(new Date()+":全部線程已到達,向目的地2出發");
						
                        Thread.sleep(new Random().nextInt(10000));
                        System.out.println(new Date()+":線程"+Thread.currentThread().getName()+"到達目的地2,當前已到達"+(cb.getNumberWaiting()+1)+",正在等候");
                        cb.await();
                        System.out.println(new Date()+":全部線程已到達,向目的地3出發");
						
                        Thread.sleep(new Random().nextInt(10000));
                        System.out.println(new Date()+":線程"+Thread.currentThread().getName()+"到達目的地3,當前已到達"+(cb.getNumberWaiting()+1)+",正在等候");
                        cb.await();
                        System.out.println(new Date()+":全部線程已到達,任務結束");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            };
            es.execute(r);
        }
        es.shutdown();
    }

}

3、CountDownLatch

1. 簡介

猶如倒計時計數器,調用CountDownLatch對象的countDown()方法就將計數器-1,當計數器到達0時,則全部等待者或者單個等待着開始執行。 ui

2. 示例

import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchTest {

    public static void main(String[] args) {
        ExecutorService es = Executors.newCachedThreadPool();
        final CountDownLatch cdOrder = new CountDownLatch(1);
        final CountDownLatch cdAnswer = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    try {
                        //Thread.sleep(new Random().nextInt(10000));
                        System.out.println(new Date()+":線程"+Thread.currentThread().getName()+"準備接受命令");
                        cdOrder.await();
                        System.out.println(new Date()+":線程"+Thread.currentThread().getName()+"已接受命令");
                        Thread.sleep(new Random().nextInt(10000));
                        System.out.println(new Date()+":線程"+Thread.currentThread().getName()+"處理命令");
                        cdAnswer.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            es.execute(r);
        }
		
        try {
            Thread.sleep(new Random().nextInt(10000));
            System.out.println(new Date()+":線程"+Thread.currentThread().getName()+"即將發佈命令");
            cdOrder.countDown();
            System.out.println(new Date()+":線程"+Thread.currentThread().getName()+"已發佈命令,正等待結果");
            cdAnswer.await();
            System.out.println(new Date()+":線程"+Thread.currentThread().getName()+"已收到全部響應結果");
        } catch (Exception e) {
            e.printStackTrace();
        }
		
        es.shutdown();
    }
}

4、Exchanger

1. 簡介

Exchanger用於兩個線程之間的數據交換。每一個線程在完成必定任務後想與對方交換數據,第一個先拿出數據的線程將一直等待第二個線程拿着數據的到來,才能彼此交換數據。 spa

2. 示例

import java.util.Date;
import java.util.Random;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Exchanger交換機 兩個線程之間用戶交換數據
 */
public class ExchangerTest {

    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        // 線程之間交換數據
        final Exchanger exchanger = new Exchanger();

        service.execute(new Runnable() {
            public void run() {
                try {
                    String data = "【數據1】";
                    System.out.println(new Date()+":"+Thread.currentThread().getName() + "準備把" + data + "換出去");
                    Thread.sleep(new Random().nextInt(10000));

                    String data2 = (String) exchanger.exchange(data);
                    System.out.println(new Date()+":"+Thread.currentThread().getName() + "換回的數據是" + data2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        service.execute(new Runnable() {
            public void run() {
                try {
                    String data = "【數據2】";
                    System.out.println(new Date()+":"+Thread.currentThread().getName() + "準備把" + data + "換出去");
                    Thread.sleep(new Random().nextInt(10000));

                    String data2 = (String) exchanger.exchange(data);
                    System.out.println(new Date()+":"+Thread.currentThread().getName() + "換回的數據是" + data2);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

    }
}
相關文章
相關標籤/搜索