Semaphore也是一个线程同步的辅助类,可以维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。
Semaphore的主要方法摘要:
void acquire()**:**从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
void release():释放一个许可,将其返回给信号量。
int availablePermits():返回此信号量中当前可用的许可数。
boolean hasQueuedThreads():查询是否有线程正在等待获取。
下面是一个例子:
1 package com.thread;
2
3 import java.util.concurrent.ExecutorService;
4 import java.util.concurrent.Executors;
5 import java.util.concurrent.Semaphore;
6
7 public class SemaphoreTest {
8 public static void main(String[] args) {
9 ExecutorService service = Executors.newCachedThreadPool();
10 final Semaphore sp = new Semaphore(3);//创建Semaphore信号量,初始化许可大小为3
11 for(int i=0;i<10;i++){
12 try {
13 Thread.sleep(100);
14 } catch (InterruptedException e2) {
15 e2.printStackTrace();
16 }
17 Runnable runnable = new Runnable(){
18 public void run(){
19 try {
20 sp.acquire();//请求获得许可,如果有可获得的许可则继续往下执行,许可数减1。否则进入阻塞状态
21 } catch (InterruptedException e1) {
22 e1.printStackTrace();
23 }
24 System.out.println(“线程” + Thread.currentThread().getName() +
25 “进入,当前已有” + (3-sp.availablePermits()) + “个并发”);
26 try {
27 Thread.sleep((long)(Math.random()*10000));
28 } catch (InterruptedException e) {
29 e.printStackTrace();
30 }
31 System.out.println(“线程” + Thread.currentThread().getName() +
32 “即将离开”);
33 sp.release();//释放许可,许可数加1
34 //下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
35 System.out.println(“线程” + Thread.currentThread().getName() +
36 “已离开,当前已有” + (3-sp.availablePermits()) + “个并发”);
37 }
38 };
39 service.execute(runnable);
40 }
41 }
42
43 }
单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。
1 package com.thread;
2 import java.util.concurrent.ExecutorService;
3 import java.util.concurrent.Executors;
4 import java.util.concurrent.Semaphore;
5 import java.util.concurrent.locks.Lock;
6 import java.util.concurrent.locks.ReentrantLock;
7
8 public class LockTest {
9 public static void main(String[] args) {
10 final Business business = new Business();
11 ExecutorService executor = Executors.newFixedThreadPool(3);
12 for(int i=0;i<3;i++)
13 {
14 executor.execute(
15 new Runnable()
16 {
17 public void run()
18 {
19 business.service();
20 }
21 }
22
23 );
24 }
25 executor.shutdown();
26 }
27
28 private static class Business
29 {
30 private int count;
31 Lock lock = new ReentrantLock();
32 Semaphore sp = new Semaphore(1);
33 public void service()
34 {
35 //lock.lock();
36 try {
37 sp.acquire(); //当前线程使用count变量的时候将其锁住,不允许其他线程访问
38 } catch (InterruptedException e1) {
39 e1.printStackTrace();
40 }
41 try {
42 count++;
43 try {
44 Thread.sleep(1000);
45 } catch (InterruptedException e) {
46 e.printStackTrace();
47 }
48 System.out.println(count);
49 } catch (RuntimeException e) {
50 e.printStackTrace();
51 }
52 finally
53 {
54 //lock.unlock();
55 sp.release(); //释放锁
56 }
57 }
58 }
59
60 }