Java 并发包中的同步器是一些用于协调多个线程执行的工具,用于实现线程之间的同步和互斥操作。这些同步器提供了不同的机制来控制线程的访问和执行顺序,以实现线程安全和并发控制。
Semaphore 是 Java 并发包中的同步器之一,用于控制对临界区资源的访问数量。它允许多个线程同时访问临界区资源,但限制了同一时间内可以访问资源的线程数量。
Semaphore 维护一个许可证计数,线程可以获取和释放这些许可证。当许可证数量为零时,线程需要等待,直到其他线程释放许可证。
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3); // 初始化信号量,允许同时访问的线程数量为3
// 创建多个线程来模拟访问临界区资源
for (int i = 1; i <= 5; i++) {
int threadId = i;
Thread thread = new Thread(() -> {
try {
semaphore.acquire(); // 获取许可证,如果没有许可证则阻塞
System.out.println("Thread " + threadId + " acquired a permit and is accessing the resource.");
Thread.sleep(2000); // 模拟访问临界区资源的耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放许可证
System.out.println("Thread " + threadId + " released the permit.");
}
});
thread.start();
}
}
}
运行结果:
Thread 1 acquired a permit and is accessing the resource.
Thread 3 acquired a permit and is accessing the resource.
Thread 2 acquired a permit and is accessing the resource.
Thread 2 released the permit.
Thread 4 acquired a permit and is accessing the resource.
Thread 5 acquired a permit and is accessing the resource.
Thread 3 released the permit.
Thread 1 released the permit.
Thread 4 released the permit.
Thread 5 released the permit.
在上述示例中,我们创建了一个 Semaphore 实例,并初始化许可证数量为 3。然后创建了多个线程,每个线程在获取许可证后访问临界区资源,模拟耗时操作后释放许可证。由于许可证数量有限,只有一部分线程能够同时访问资源,其他线程需要等待。
CountDownLatch 是 Java 并发包中的同步器之一,用于实现一种等待机制,允许一个或多个线程等待其他线程完成一组操作后再继续执行。
它通过维护一个计数器来实现等待和通知的机制。
在创建 CountDownLatch 时,需要指定初始计数值,每次调用 countDown() 方法会减少计数值,当计数值达到零时,等待的线程会被唤醒继续执行。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) {
int numberOfTasks = 3;
CountDownLatch latch = new CountDownLatch(numberOfTasks);
// 创建多个线程来模拟完成任务
for (int i = 1; i <= numberOfTasks; i++) {
int taskId = i;
Thread thread = new Thread(() -> {
try {
System.out.println("Task " + taskId + " is executing...");
Thread.sleep(2000); // 模拟任务执行耗时
System.out.println("Task " + taskId + " is completed.");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown(); // 完成任务后减少计数
}
});
thread.start();
}
try {
System.out.println("Main thread is waiting for tasks to complete...");
latch.await(); // 等待所有任务完成
System.out.println("All tasks are completed. Main thread continues.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
Task 1 is executing...
Main thread is waiting for tasks to complete...
Task 2 is executing...
Task 3 is executing...
Task 1 is completed.
Task 2 is completed.
Task 3 is completed.
All tasks are completed. Main thread continues.
在上述示例中,我们创建了一个 CountDownLatch 实例,并初始化计数值为 3。然后创建了多个线程来模拟完成任务,每个线程执行完任务后调用 countDown() 方法减少计数。主线程在执行 latch.await() 时等待计数值为零,等待所有任务完成后继续执行。
使用 CountDownLatch 可以实现多个线程之间的协调,确保某些操作在其他操作完成后再继续执行。
CyclicBarrier 是 Java 并发包中的同步器之一,用于实现一组线程在达到一个共同点之前等待彼此,并在达到共同点后继续执行。它可以被重置并重新使用,适用于需要多个线程协同工作的场景。
CyclicBarrier 维护一个计数器和一个栅栏动作(barrier action)。当线程调用 await() 方法时,计数器减少,当计数器达到零时,所有等待的线程会被唤醒并继续执行,同时会执行栅栏动作。计数器可以被重置,并且可以设置栅栏动作,在达到共同点后执行。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
int numberOfThreads = 3;
Runnable barrierAction = () -> System.out.println("All threads reached the barrier!");
CyclicBarrier barrier = new CyclicBarrier(numberOfThreads, barrierAction);
// 创建多个线程来模拟并行执行任务
for (int i = 1; i <= numberOfThreads; i++) {
int threadId = i;
Thread thread = new Thread(() -> {
try {
System.out.println("Thread " + threadId + " is performing its task.");
Thread.sleep(2000); // 模拟任务执行耗时
System.out.println("Thread " + threadId + " has reached the barrier.");
barrier.await(); // 等待其他线程达到栅栏点
System.out.println("Thread " + threadId + " continues after the barrier.");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
thread.start();
}
}
}
运行结果:
Thread 1 is performing its task.
Thread 3 is performing its task.
Thread 2 is performing its task.
Thread 2 has reached the barrier.
Thread 3 has reached the barrier.
Thread 1 has reached the barrier.
All threads reached the barrier!
Thread 1 continues after the barrier.
Thread 2 continues after the barrier.
Thread 3 continues after the barrier.
在上述示例中,我们创建了一个 CyclicBarrier 实例,初始化等待的线程数量为 3,并设置了栅栏动作。
然后创建多个线程,每个线程模拟执行任务后等待其他线程达到栅栏点,当所有线程都达到栅栏点时,栅栏动作会被执行。
使用 CyclicBarrier 可以实现多线程协同工作的场景,确保所有线程在某个共同点之前等待彼此,并在达到共同点后继续执行。
package com.lf.java.basic.concurrent;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class MultipleCyclicBarrierExample {
public static void main(String[] args) {
int numberOfThreads = 3;
int numberOfRounds = 3;
Runnable barrierAction = () -> System.out.println("All threads reached the barrier!");
for (int round = 1; round <= numberOfRounds; round++) {
CyclicBarrier barrier = new CyclicBarrier(numberOfThreads, barrierAction);
System.out.println("Round " + round + ": Starting tasks");
// 创建多个线程来模拟并行执行任务
for (int i = 1; i <= numberOfThreads; i++) {
int threadId = i;
int finalRound = round;
Thread thread = new Thread(() -> {
try {
System.out.println("Thread " + threadId + " is performing its task for Round " + finalRound);
Thread.sleep(2000); // 模拟任务执行耗时
System.out.println("Thread " + threadId + " has reached the barrier for Round " + finalRound);
barrier.await(); // 等待其他线程达到栅栏点
System.out.println("Thread " + threadId + " continues after the barrier for Round " + finalRound);
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
thread.start();
}
// 等待所有线程完成当前轮次的任务
try {
Thread.sleep(3000); // 等待一段时间以观察效果
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Round " + round + ": All tasks completed\n");
// 让当前轮次的所有线程都离开栅栏点,以便重新使用
barrier.reset();
}
}
}
运行结果:
Round 1: Starting tasks
Thread 1 is performing its task for Round 1
Thread 2 is performing its task for Round 1
Thread 3 is performing its task for Round 1
Thread 3 has reached the barrier for Round 1
Thread 2 has reached the barrier for Round 1
Thread 1 has reached the barrier for Round 1
All threads reached the barrier!
Thread 2 continues after the barrier for Round 1
Thread 1 continues after the barrier for Round 1
Thread 3 continues after the barrier for Round 1
Round 1: All tasks completed
Round 2: Starting tasks
Thread 1 is performing its task for Round 2
Thread 2 is performing its task for Round 2
Thread 3 is performing its task for Round 2
Thread 3 has reached the barrier for Round 2
Thread 2 has reached the barrier for Round 2
Thread 1 has reached the barrier for Round 2
All threads reached the barrier!
Thread 1 continues after the barrier for Round 2
Thread 3 continues after the barrier for Round 2
Thread 2 continues after the barrier for Round 2
Round 2: All tasks completed
Round 3: Starting tasks
Thread 1 is performing its task for Round 3
Thread 2 is performing its task for Round 3
Thread 3 is performing its task for Round 3
Thread 1 has reached the barrier for Round 3
Thread 2 has reached the barrier for Round 3
Thread 3 has reached the barrier for Round 3
All threads reached the barrier!
Thread 3 continues after the barrier for Round 3
Thread 1 continues after the barrier for Round 3
Thread 2 continues after the barrier for Round 3
Round 3: All tasks completed
在上述示例中,我们模拟了多轮任务协同。每一轮都创建一个新的 CyclicBarrier 实例,用于协调线程的等待和通知。在每一轮的任务完成后,我们使用 barrier.reset() 来重置计数器,以便进行下一轮的任务协同。
运行这个示例可以看到多轮任务协同的效果,每一轮的任务都会等待所有线程完成后再继续,然后重置计数器以准备下一轮。
Phaser 是 Java 并发包中的同步器之一,它提供了更灵活的多阶段线程协调机制,适用于需要分阶段进行多个任务的并行执行和协调的场景。Phaser 可以用于更复杂的同步需求,例如循环的多阶段任务协同。
Phaser 维护了一个计数器和多个阶段(phase)。在每个阶段,线程可以注册、等待和注销,以及在某个阶段到达时执行特定的操作。
import java.util.concurrent.Phaser;
public class PhaserExample {
public static void main(String[] args) {
int numberOfThreads = 3;
int numberOfPhases = 3;
Phaser phaser = new Phaser(numberOfThreads) {
@Override
protected boolean onAdvance(int phase, int registeredParties) {
System.out.println("Phase " + phase + " completed.");
return phase == numberOfPhases - 1 || registeredParties == 0;
}
};
// 创建多个线程来模拟并行执行任务
for (int i = 0; i < numberOfThreads; i++) {
int threadId = i;
Thread thread = new Thread(() -> {
for (int phase = 0; phase < numberOfPhases; phase++) {
System.out.println("Thread " + threadId + " is in Phase " + phase);
phaser.arriveAndAwaitAdvance(); // 等待其他线程到达当前阶段
}
});
thread.start();
}
}
}
运行结果:
Thread 0 is in Phase 0
Thread 1 is in Phase 0
Thread 2 is in Phase 0
Phase 0 completed.
Thread 2 is in Phase 1
Thread 1 is in Phase 1
Thread 0 is in Phase 1
Phase 1 completed.
Thread 1 is in Phase 2
Thread 2 is in Phase 2
Thread 0 is in Phase 2
Phase 2 completed.
在上述示例中,我们创建了一个 Phaser 实例,设置初始注册线程数量为 3。然后,我们创建多个线程来模拟并行执行任务,每个线程都会在每个阶段调用 phaser.arriveAndAwaitAdvance() 等待其他线程到达当前阶段。当所有线程都到达后,onAdvance() 方法会被调用,用于执行阶段结束后的操作。
Phaser 提供了更灵活的多阶段协同机制,适用于需要多个阶段的任务协同和并行执行的场景。它还支持动态添加或删除等待线程,使其更适用于动态变化的并发需求。