首頁 > 軟體

Java並行程式設計號誌Semapher

2022-04-15 19:00:57

Semapher號誌也是Java中的一個同步器,與CountDownLatch和CycleBarrier不同的是,它內部的計數器是遞增的,並且在一開始初始化Semaphoer時可以指定一個初始值,但是並不需要知道需要同步的執行緒個數,而是在需要同步的地方呼叫acquire方法時指定需要同步的執行緒個數。

我們通過下面一個例子來看一下Semapher效果:

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

public class SemaphoreTest {

    private static Semaphore semaphore = new Semaphore(0);
    public static void main(String[] args) throws InterruptedException{
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        semaphore.acquire(2);
        System.out.println("all child thread over!");
        executorService.shutdown();

    }
}

如上程式碼首先建立了一個號誌範例,建構函式的入參為0,說明當前號誌計數器的值為0。然後,main函數向執行緒池新增兩個執行緒任務,在每個執行緒內部呼叫號誌的acquire方法,傳參為2說明呼叫acquire方法的執行緒會一直阻塞,知道號誌的技術變為2才會返回。如果構造Semaphore時,傳遞的引數為N,並在M個執行緒中呼叫了該號誌的release方法,那麼在呼叫acquire使M個執行緒同步時傳遞的引數應該是M+N。

下面舉例子來模擬CycliBarrier複用的功能,程式碼如下:

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

public class Semaphoer {

    private static Semaphore semaphore = new Semaphore(0);
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "A task over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "A task over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        semaphore.acquire(2);
        System.out.println("task A is over");
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "B task over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "B task over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        semaphore.acquire(2);
        System.out.println("task B is over");
        executorService.shutdown();

    }
}

如上程式碼首先將執行緒A和執行緒B加入到執行緒池。主執行緒執行程式碼(1)後被阻塞。執行緒A和執行緒B呼叫release方法後號誌的值變為了2,這時候主執行緒的aquire方法會在獲取到2個號誌後返回(返回後當前號誌值為0)。然後主執行緒新增執行緒C和執行緒D到執行緒池,之後主執行緒執行程式碼(2)後被阻塞(因為主執行緒要獲取2個號誌,而當前號誌個數為0)。當執行緒C和執行緒D執行完release 方法後,主執行緒才返回。從本例子可以看出,Semaphore 在某種程度上實現了CyclicBarrier 的複用功能。

到此這篇關於Java並行程式設計號誌Semapher的文章就介紹到這了,更多相關Java Semapher內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


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