原创转载请注明出处:http://agilestyle.iteye.com/blog/2342878
Semaphore所提供的功能完全是synchronized关键字的升级版,但它提供的功能更加的强大和方便,主要的作用是控制线程并发的数量。
Semaphore(int permits)
设置permits为1
Service.java
package org.fool.java.concurrent.semaphore; import java.util.concurrent.Semaphore; public class Service { private Semaphore semaphore = new Semaphore(1); public void testMethod() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " begin timer=" + System.currentTimeMillis()); Thread.sleep(5000); System.out.println(Thread.currentThread().getName() + " end timer=" + System.currentTimeMillis()); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } }
Note:
permits代表同一时间内,最多允许多少个线程同时执行acquire()和release()之间的代码。
本例设置为1,所以最多只有1个线程同时执行acquire()和release()之间的代码。
ThreadA.java
package org.fool.java.concurrent.semaphore; public class ThreadA implements Runnable { private Service service; public ThreadA(Service service) { this.service = service; } @Override public void run() { service.testMethod(); } }
ThreadB.java
package org.fool.java.concurrent.semaphore; public class ThreadB implements Runnable { private Service service; public ThreadB(Service service) { this.service = service; } @Override public void run() { service.testMethod(); } }
ThreadC.java
package org.fool.java.concurrent.semaphore; public class ThreadC implements Runnable { private Service service; public ThreadC(Service service) { this.service = service; } @Override public void run() { service.testMethod(); } }
SemaphoreTest.java
package org.fool.java.concurrent.semaphore; public class SemaphoreTest { public static void main(String[] args) { Service service = new Service(); Thread a = new Thread(new ThreadA(service)); Thread b = new Thread(new ThreadA(service)); Thread c = new Thread(new ThreadA(service)); a.setName("A"); b.setName("B"); c.setName("C"); a.start(); b.start(); c.start(); } }
Run
Note:
private Semaphore semaphore = new Semaphore(1);
由于定义了最多1个线程执行acquire()和release()之间的代码,所以打印的结果就是3个线程是同步的,线程A执行结束的时间和线程B执行开始的时间相同,线程B执行结束的时间和线程C还行开始的时间相同。
修改Service.java,设置permits为2
private Semaphore semaphore = new Semaphore(2);
再次Run SemaphoreTest
Note:
由于定义了最多2个线程执行acquire()和release()之间的代码,所以线程A和线程B执行开始的时间是相同的,需要注意的是,对Semaphore的构造方法传递的参数permits值如果大于1时,该类并不能保证线程的安全性,因为还是有可能会出现多个线程共同访问实例变量,导致出现脏读。
Semaphore(int permits, boolean fair)
有些时候,获得permits的顺序与线程启动的顺序有关,这时信号量就要分为公平和非公平的。
公平信号量是获得锁的顺序与线程启动的顺序有关,但不代表100%地获得信号量,仅仅是在概率上能得到保证。
非公平信号量即获得锁的顺序与线程启动的顺序无关。
Service.java
package org.fool.java.concurrent.semaphore.fair; import java.util.concurrent.Semaphore; public class Service { private boolean isFair = false; private Semaphore semaphore = new Semaphore(1, isFair); public void testMethod() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } } }
Note:
设置了非公平信号量
private boolean isFair = false;
ThreadA.java
package org.fool.java.concurrent.semaphore.fair; public class ThreadA implements Runnable { private Service service; public ThreadA(Service service) { this.service = service; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " invoked..."); service.testMethod(); } }
FairTest.java
package org.fool.java.concurrent.semaphore.fair; public class FairTest { public static void main(String[] args) { Service service = new Service(); Thread a = new Thread(new ThreadA(service)); a.start(); for(int i = 0; i < 4; i++) { new Thread(new ThreadA(service)).start(); } } }
Run
非公平信号量运行的效果是线程启动的顺序与调用semaphore.acquire()的顺序无关,也就是线程先启动了并不代表获得permits
修改Service.java,设置公平信号量
private boolean isFair = true;
再Run
公平信号量运行的效果是线程启动的顺序与调用semaphore.acquire()的顺序有关,也就是先启动的线程优先获得permits
相关推荐
【Semaphore详解】Semaphore是Java并发包`java.util.concurrent`中的一个工具类,它主要用于控制并发访问的线程数量。Semaphore可以被理解为一种资源的许可证,每个许可证代表了一个可访问的资源实例。线程在执行前...
Semaphore(int permits, boolean fair) ``` 创 建 具 有 给 定 的 许 可 数 和 给 定 的 公 正 设 置 的Semaphore。 Semaphore当前在多线程环境下被扩放用法,操作系统的信号量是个很重要的概念,在进程掌握方面都...
2. `Semaphore(int permits, boolean fair)`:创建具有指定初始许可数的信号量,并可以选择是否采用公平策略。公平策略意味着等待时间最长的线程将优先获取许可,而不公平策略则没有这样的保证。 **二、Semaphore的...
2. `Semaphore(int permits, boolean fair)`:除了指定许可数量外,还可以设置是否启用公平策略。公平策略意味着等待最长时间的线程优先获得许可。 Semaphore提供以下核心方法: 1. `void acquire()`:获取一个...
2. `Semaphore(int permits, boolean fair)`: 创建具有给定许可数的公平(true)或非公平(false)Semaphore。 Semaphore 的方法 1. `acquire()`: 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则...
- `Semaphore(int permits)`构造函数初始化信号量,参数`permits`表示初始的许可数量。 - `acquire()`方法用于获取一个许可,如果当前许可数量大于零,则消耗一个许可,否则线程被阻塞等待。 - `acquire(int ...
在Java 5引入并发包`java.util.concurrent`后,信号量作为`Semaphore`类被添加,成为并发编程的一个新特性。 信号量的核心概念是许可(permits),它可以看作是系统中可用资源的数量。当一个线程想要访问公共资源时...
1. `Semaphore(int permits)`:默认是非公平策略,创建一个具有指定许可数量的Semaphore。 2. `Semaphore(int permits, boolean fair)`:允许指定是否采用公平策略。公平策略意味着按照线程等待的顺序分配许可,而非...
Semaphore(int permits, boolean fair) // 创建指定数量的许可证的信号量,并指定是否为公平模式 ``` ### 代码示例 下面是一个简单的Semaphore使用示例,模拟了5个资源(停车位)供20个线程(车辆)共享的情况: ...
this.semaphore = new Semaphore(permits); } public void acquire() throws InterruptedException { semaphore.acquire(); } public void release() { semaphore.release(); } } ``` ### 分布式锁类 ##...
public Semaphore(int permits);//参数permits表示可用的许可数 Semaphore类中最重要的三个方法是: 1. public void acquire() throws InterruptedException {}; //获得一个许可 2. public boolean tryAcquire() ...
在Java编程语言中,`Semaphore`是一个非常重要的同步工具类,它源于`java.util.concurrent`包,用于控制同时访问特定资源的线程数量。标题"SOI-ThreadsSemaphore-I"暗示了这个项目或教程可能专注于如何在多线程环境...
5. `tryAcquire(int permits)`: 尝试获取指定数量的许可证。如果足够数量的许可证可用,立即返回true;否则,返回false。 在实际应用中,信号量常用于限制线程池大小、保护临界区或实现线程之间的协作。例如,在一...
首先,我们需要了解Java中实现线程通信的关键类和接口,如`Object`类的`wait()`、`notify()`和`notifyAll()`方法,以及`java.util.concurrent`包下的`BlockingQueue`、`Semaphore`、`CyclicBarrier`等工具类。...