Concurrent - Semaphore - Semaphore(int permits)
原创转载请注明出处: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