Java Semaphore
最后修改:2025 年 2 月 15 日
在本文中,我们将展示如何使用 Semaphore
同步 Java 线程。
Semaphore
是一种同步工具,它通过一组许可来控制对共享资源的访问。它对于管理有限的资源非常有用,例如数据库连接或线程池,在这些情况下,只有一定数量的线程可以同时访问该资源。
Semaphore
使用一定数量的许可进行初始化。 线程可以使用 acquire
方法获取许可,并使用 release
方法释放许可。 如果没有可用的许可,线程将阻塞,直到另一个线程释放许可为止。
Semaphore 示例
以下示例演示如何使用 Semaphore
来控制对共享资源的访问。
import java.util.concurrent.Semaphore; class SharedResource { private final Semaphore semaphore; public SharedResource(int permits) { this.semaphore = new Semaphore(permits); } public void useResource() { try { semaphore.acquire(); // Acquire a permit System.out.println(Thread.currentThread().getName() + " is using the resource"); Thread.sleep(2000); // Simulate resource usage } catch (InterruptedException e) { throw new RuntimeException(e); } finally { System.out.println(Thread.currentThread().getName() + " is releasing the resource"); semaphore.release(); // Release the permit } } } class Worker implements Runnable { private final SharedResource sharedResource; public Worker(SharedResource sharedResource) { this.sharedResource = sharedResource; } @Override public void run() { sharedResource.useResource(); } } void main() throws InterruptedException { SharedResource sharedResource = new SharedResource(2); // Allow 2 permits Thread t1 = new Thread(new Worker(sharedResource), "Thread-1"); Thread t2 = new Thread(new Worker(sharedResource), "Thread-2"); Thread t3 = new Thread(new Worker(sharedResource), "Thread-3"); Thread t4 = new Thread(new Worker(sharedResource), "Thread-4"); t1.start(); t2.start(); t3.start(); t4.start(); t1.join(); t2.join(); t3.join(); t4.join(); }
在此程序中,使用 Semaphore
限制对共享资源的访问。 一次只能有两个线程可以访问该资源,因为信号量使用两个许可进行初始化。
private final Semaphore semaphore; public SharedResource(int permits) { this.semaphore = new Semaphore(permits); }
SharedResource
类使用具有指定数量许可的 Semaphore
初始化。
semaphore.acquire(); // Acquire a permit
线程在访问资源之前获取许可。 如果没有可用的许可,线程将阻塞。
semaphore.release(); // Release the permit
使用资源后,线程释放许可,允许其他线程获取它。
SharedResource sharedResource = new SharedResource(2); // Allow 2 permits
SharedResource
使用两个许可进行初始化,这意味着一次只能有两个线程可以访问该资源。
$ java Main.java Thread-1 is using the resource Thread-2 is using the resource Thread-1 is releasing the resource Thread-2 is releasing the resource Thread-3 is using the resource Thread-4 is using the resource Thread-3 is releasing the resource Thread-4 is releasing the resource
具有公平性的 Semaphore
以下示例演示如何使用具有公平性的 Semaphore
。 启用公平性后,线程将按照请求的顺序获取许可。
import java.util.concurrent.Semaphore; class SharedResource { private final Semaphore semaphore; public SharedResource(int permits, boolean fair) { this.semaphore = new Semaphore(permits, fair); } public void useResource() { try { semaphore.acquire(); // Acquire a permit System.out.println(Thread.currentThread().getName() + " is using the resource"); Thread.sleep(2000); // Simulate resource usage } catch (InterruptedException e) { throw new RuntimeException(e); } finally { System.out.println(Thread.currentThread().getName() + " is releasing the resource"); semaphore.release(); // Release the permit } } } class Worker implements Runnable { private final SharedResource sharedResource; public Worker(SharedResource sharedResource) { this.sharedResource = sharedResource; } @Override public void run() { sharedResource.useResource(); } } void main() throws InterruptedException { SharedResource sharedResource = new SharedResource(2, true); // Allow 2 permits with fairness Thread t1 = new Thread(new Worker(sharedResource), "Thread-1"); Thread t2 = new Thread(new Worker(sharedResource), "Thread-2"); Thread t3 = new Thread(new Worker(sharedResource), "Thread-3"); Thread t4 = new Thread(new Worker(sharedResource), "Thread-4"); t1.start(); t2.start(); t3.start(); t4.start(); t1.join(); t2.join(); t3.join(); t4.join(); }
在此程序中,Semaphore
启用公平性进行初始化。 这确保了线程按照它们请求的顺序获取许可。
public SharedResource(int permits, boolean fair) { this.semaphore = new Semaphore(permits, fair); }
Semaphore
启用公平性进行初始化,确保线程按照它们请求的顺序获取许可。
$ java Main.java Thread-1 is using the resource Thread-2 is using the resource Thread-1 is releasing the resource Thread-2 is releasing the resource Thread-3 is using the resource Thread-4 is using the resource Thread-3 is releasing the resource Thread-4 is releasing the resource
带有 Semaphore 示例的线程池
以下示例演示如何使用 Semaphore
来实现线程池。 线程池将并发执行的任务数量限制为固定大小。
import java.util.concurrent.Semaphore; class Task implements Runnable { private final int taskId; private final Semaphore semaphore; public Task(int taskId, Semaphore semaphore) { this.taskId = taskId; this.semaphore = semaphore; } @Override public void run() { try { semaphore.acquire(); // Acquire a permit System.out.println("Task " + taskId + " is running on " + Thread.currentThread().getName()); Thread.sleep(2000); // Simulate task execution } catch (InterruptedException e) { throw new RuntimeException(e); } finally { System.out.println("Task " + taskId + " is completed"); semaphore.release(); // Release the permit } } } void main() throws InterruptedException { int poolSize = 3; // Maximum number of concurrent tasks Semaphore semaphore = new Semaphore(poolSize); // Create and start 10 tasks for (int i = 1; i <= 10; i++) { Thread thread = new Thread(new Task(i, semaphore)); thread.start(); } // Wait for all tasks to complete Thread.sleep(10000); // Adjust sleep time as needed System.out.println("All tasks completed"); }
在此程序中,使用 Semaphore
将并发执行的任务数量限制为固定大小(在本例中为 3)。 每个任务在执行之前获取许可,并在完成后释放它。
semaphore.acquire(); // Acquire a permit
任务在开始执行之前获取许可。 如果没有可用的许可,该任务将阻塞,直到释放许可为止。
semaphore.release(); // Release the permit
执行完成后,任务释放许可,允许另一个任务获取它。
int poolSize = 3; // Maximum number of concurrent tasks Semaphore semaphore = new Semaphore(poolSize);
Semaphore
使用大小为 3 的池进行初始化,这意味着只有 3 个任务可以并发运行。
$ java Main.java Task 1 is running on Thread-0 Task 2 is running on Thread-1 Task 3 is running on Thread-2 Task 1 is completed Task 4 is running on Thread-3 Task 2 is completed Task 5 is running on Thread-4 Task 3 is completed Task 6 is running on Thread-5 Task 4 is completed Task 7 is running on Thread-6 Task 5 is completed Task 8 is running on Thread-7 Task 6 is completed Task 9 is running on Thread-8 Task 7 is completed Task 10 is running on Thread-9 Task 8 is completed Task 9 is completed Task 10 is completed All tasks completed
来源
在本文中,我们展示了如何使用 Semaphore 同步 Java 线程以进行资源管理。
作者
列出所有Java教程。