原味儿:https://blog.csdn.net/u013851082/article/details/70208246
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 }