Semaphore类
JDK API中描述为:一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一
个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。将信号量初始化为 1,使得它在使用时最多只有一个可用的许可,从而可用作一个相互排斥的锁。这通常也称为二进制信号量,因为它只能有两种状态:一个可用的许可,或零个可用的许可。按此方式使用时,二进制信号量具有某种属性(与很多 Lock 实现不同),即可以由线程释放“锁”,而不是由所有者(因为信号量没有所有权的概念)。在某些专门的上下文(如死锁恢复)中这会很有用。
package com.jjyy.customer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.SynchronousQueue;
/*Semaphore与SynchronousQueue的混合使用。
由于Semaphore只有1个许可权,所以谁先拿到谁执行,然后释放,保证依次执行,
用锁也行,只要保证一个线程执行即可
SynchronousQueue是必须有其他线程取的动作,这样一一对应
*/
public class Test {
public static void main(String[] args) {
//定义一个许可权为1的信号灯
final Semaphore semaphore = new Semaphore(1);
//产生的结果无序
final SynchronousQueue<String> queue = new SynchronousQueue<String>();
/*
//产生10个线程
for(int i=0;i<10;i++){
new Thread(new Runnable(){
@Override
public void run() {
try {
semaphore.acquire(); //获取许可
String input = queue.take(); //获取并移除此队列的头
String output = TestDoIT.doSome(input);
System.out.println(Thread.currentThread().getName()+ ":" + output);
semaphore.release(); //释放许可
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}*/
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
executor.execute(new Runnable() {
public void run() {
try {
semaphore.acquire(); //获取许可
String input = queue.take(); //获取并移除此队列的头
String output = TestDoIT.doSome(input);
System.out.println(Thread.currentThread().getName()+ ":" + output);
semaphore.release(); //释放许可
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
System.out.println("begin:"+(System.currentTimeMillis()/1000));
for(int i=0;i<10;i++){ //这行不能改动
String input = i+""; //这行不能改动
try {
queue.put(input); //将指定元素添加到此队列
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//不能改动此TestDo类
class TestDoIT {
public static String doSome(String input){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String output = input + ":"+ (System.currentTimeMillis() / 1000);
return output;
}
}
执行结果:
begin:1439963505
pool-1-thread-1:0:1439963506
pool-1-thread-2:1:1439963507
pool-1-thread-3:2:1439963508
pool-1-thread-4:3:1439963509
pool-1-thread-5:4:1439963510
pool-1-thread-6:5:1439963511
pool-1-thread-7:6:1439963512
pool-1-thread-9:7:1439963513
pool-1-thread-8:8:1439963514
pool-1-thread-10:9:1439963515