- 倒計時門閂
倒計時門閂會導致一條或多條線程在"門口"一直等待,直到另一條線程打開這扇門,線程才得以繼續運行。它是由一個計數變量和兩個操作數組成,這兩個操作分別是"導致一條線程等待直到計數變爲0"以及"遞減計數變量"。
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
int count = 10;
CountDownLatch countDownLatch = new CountDownLatch(10);
ExecutorService executorService = Executors.newFixedThreadPool(count);
for (int i = 0; i < count; i++) {
executorService.execute(() -> {
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName());
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("done");
}
}
- 同步屏障
同步屏障允許一組線程彼此相互等待,直到抵達某個公共的屏障點。因爲該屏障在等待線程被釋放之後可以重用,所以稱它爲可循環使用的屏障。該同步器對於固定數量並且互相之間必須不時等待彼此的多線程應用很有用。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicBarrierDemo {
public static void main(String[] args) {
int count = 10;
CyclicBarrier cyclicBarrier = new CyclicBarrier(count, () -> System.out.println("線程全部執行完成"));
ExecutorService executorService = Executors.newFixedThreadPool(count);
for (int i = 0; i < count; i++) {
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(5000L);
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
}
executorService.shutdown();
}
}
- 交換器
交換器提供一個線程彼此之間能夠交換對象的同步點。每條線程都會往這個交換器的exchange()方法傳入一些對象,匹配夥伴線程,同時接受夥伴線程中的對象作爲返回值。在諸如遺傳算法和管道設計的應用程序中,交換器會很有用。
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExchangerDemo {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
Exchanger<String> exchanger = new Exchanger<>();
executorService.execute(() -> {
try {
String result = exchanger.exchange("one");
System.out.println(Thread.currentThread().getName() + ": " + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
executorService.execute(() -> {
try {
String result = exchanger.exchange("two");
System.out.println(Thread.currentThread().getName() + ": " + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
executorService.shutdown();
}
}
- 信號量
信號量維護了一組許可證(permit),以約束訪問被限制資源的線程數。當沒有可用的許可證時,線程的獲取嘗試會一直阻塞,直到其他的線程釋放一個許可證。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
public static void main(String[] args) {
int count = 5;
Semaphore semaphore = new Semaphore(count);
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
executorService.submit(() -> {
try {
semaphore.acquire();
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
semaphore.release();
});
}
executorService.shutdown();
}
}