信號
![](https://cdn.codegym.cc/images/article/5b56b330-d15d-450e-9d26-15f951f2a98a/1024.jpeg)
當使用文件系統時需要限制線程數時,通常會使用信號量。通過計數器控制對文件或其他共享資源的訪問。如果其值大於零,則允許訪問,但同時計數器會減少。
在計數器歸零的那一刻,當前線程將被阻塞,直到資源被另一個線程釋放。必須通過構造函數設置權限參數的數量。
您需要單獨選擇此參數,具體取決於您的計算機或筆記本電腦的功率。
public class Main {
public static void main(String[] args) {
Semaphore sem = new Semaphore(1);
CommonResource res = new CommonResource();
new Thread(new MyThread(res, sem, "MyThread_1")).start();
new Thread(new MyThread(res, sem, "MyThread_2")).start();
new Thread(new MyThread(res, sem, "MyThread_3")).start();
}
}
class CommonResource {
int value = 0;
}
class MyThread implements Runnable {
CommonResource commonResource;
Semaphore semaphore;
String name;
MyThread(CommonResource commonResource, Semaphore sem, String name) {
this.commonResource = commonResource;
this.semaphore = sem;
this.name = name;
}
public void run() {
try {
System.out.println(name + "waiting permission");
semaphore.acquire();
commonResource.value = 1;
for (int i = 1; i < 7; i++) {
System.out.println(this.name + ": " + commonResource.value);
commonResource.value++;
Thread.sleep(150);
}
} catch (InterruptedException e) {
System.out.println(e.getMessage() + " " + name);
Thread.currentThread().interrupt();
}
System.out.println(name + "releases permission");
semaphore.release();
}
}
CountDownLatch 等
CountDownLatch - 允許多個線程等待,直到對其他線程執行的一定數量的操作完成。一個例子是應用程序的安裝:直到您接受使用條款,它才會開始,直到您選擇一個文件夾來安裝新程序,等等。為此有一個特殊的countDown()方法- 此方法將倒計時計數器減一。
一旦計數歸零,await 中的所有等待線程將繼續其工作,並且所有後續的 await 調用將不等待而通過。遞減計數器是一次性計數器,不能重置。
CyclicBarrier - 用於在某一時刻同步給定數量的線程。當 N 個線程調用 await(...) 方法並阻塞時達到屏障。之後,計數器被重置為原來的值,等待的線程將被釋放。此外,如果需要,可以在取消阻塞線程和重置計數器之前運行自定義代碼。為此,通過構造函數傳遞一個實現了Runnable接口的對象。
Exchanger<V> — Exchanger類用於線程之間的數據交換。它是類型化的,類型是線程需要交換的數據類型。
使用此類唯一的exchange()方法交換數據:
V exchange(V x) throws InterruptedException
V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException
x 參數表示要交換的數據緩衝區。該方法的第二種形式還定義了超時參數timeout 和unit,即用於超時參數的時間單位類型。
Phaser類允許您同步表示整體操作執行中的單個階段或階段的線程。Phaser定義了一個同步對象,它等待某個階段完成。Phaser然後進入下一階段或階段並等待它再次完成。
使用Phaser類時,通常首先創建其對象。接下來,我們需要註冊所有參與者。要為每個參與者註冊,調用register()方法,或者您可以通過將所需數量的參與者傳遞給Phaser構造函數來不使用此方法。
然後每個參與者執行一組特定的動作,這些動作構成了這個階段。Phaser同步器等待所有參與者完成階段的執行。要通知同步器該階段已結束,參與者必須調用arrive()或arriveAndAwaitAdvance()方法。然後同步器進入下一階段。