在学习信号量之前,需要了解一下Java中的信号量是怎么回事:
在Java中,我们会这样定义一个信号量Semaphore sp = new Semaphore(3);,其中数字 3 代表该信号量掌管的许可证(permits)的数量,
在同一时间,最多只有三个线程获得许可证,因为我们定义信号量时声明掌管三个许可证,获得许可证的方法是sp.acquire();,该方法时线程阻塞的
,一个线程在请求获取一个许可证,在没获得许可证时只能一直等待,等到另外一个线程释放了许可证,才有机会获得许可证,释放一个许可证的方法
sp.release();。总结:Java中的信号量可以用来控制最多允许多少个线程同一时间访问共享资源,在本代码中,就是同时允许三个线程访问共享资源。
对共享资源的操作放在sp.acquire();和sp.release();之间。
package three.day.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final Semaphore sp = new Semaphore(3);
for(int i=0;i<3;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
sp.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"进入,当前已有" + (3-sp.availablePermits()) + "个并发");
try {
Thread.sleep((long)(Math.random()*10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"即将离开");
sp.release();
//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
System.out.println("线程" + Thread.currentThread().getName() +
"已离开,当前已有" + (3-sp.availablePermits()) + "个并发");
}
};
service.execute(runnable);
}
service.shutdown();
}
}