使用Semaphore做并发个数控制

 

Semaphore可以控制某个资源可被同时访问的个数,acquire()获取一个许可,如果没有就等待,而release()释放一个许可。比如在Windows下可以设置共享文件的最大客户端访问个数。

另外重入锁ReentrantLock也可以实现该功能,但实现上代码也要复杂些。

 

SemaPhore,一个信号量对象,可以定义信号量的个数,通过该信号量控制线程同步的数量。例如我们只允许同步三个线程进入共享资源,其它线程都阻塞。

好比,厕所有三个坑,十个人进去,每次只能进去三个。采用信号灯来实现。

其优势为可以被其它线程唤醒,如果使用互斥锁,那么一旦出现异常,该锁将不会释放,该锁只能由自己释放。比如:一个人上厕所,如果采用互斥锁,那么当该人晕倒在厕所时,这个厕所就不能被使用了。如果使用信号灯互斥,那么能够找到物业人员打开厕所,救人并接着使用。

 

Java代码   收藏代码
  1. //构造方法摘要  
  2. Semaphore(int permits)   
  3.           //创建具有给定的许可数和非公平的公平设置的 Semaphore。  
  4. Semaphore(int permits, boolean fair)   
  5.           //创建具有给定的许可数和给定的公平设置的 Semaphore。  
//构造方法摘要
Semaphore(int permits) 
          //创建具有给定的许可数和非公平的公平设置的 Semaphore。
Semaphore(int permits, boolean fair) 
          //创建具有给定的许可数和给定的公平设置的 Semaphore。

 

下面的Demo,启动7个线程,每次只让三个线程工作,其它线程阻塞。三个线程的工作时间为一个10000以内的随机数。

 

Java代码   收藏代码
  1. package tags;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4.   
  5. import java.util.concurrent.Executors;  
  6.   
  7. import  
  8.   
  9. java.util.concurrent.Semaphore;  
  10.   
  11. public class TestSemaphore {  
  12.   
  13.     public static void  main(String[] args) {  
  14.   
  15.         ExecutorService exec = Executors.newCachedThreadPool();  
  16.   
  17.         // 只能5个线程同时访问  
  18.         final Semaphore sp = new    Semaphore(3);  
  19.   
  20.         // 模拟10个客户端访问  
  21.         for (int index = 0; index < 7; index++) {  
  22.             Runnable rb = new Runnable() {  
  23.                 public void run() {  
  24.                     try {  
  25.                         sp.acquire(); // 获取许可  
  26.                           
  27.                         System.out.println("线程" + Thread.currentThread().getName() +     
  28.                                 "进入,当前已有" + (3-sp.availablePermits()) + "个并发");    
  29.                             //availablePermits()  返回此信号量中当前可用的许可数。  
  30.                           
  31.                         Thread.sleep((long) (Math.random() * 10000));                         
  32.                         System.out.println("线程" + Thread.currentThread().getName() + "即将离开");   
  33.                           
  34.                         sp.release();// 访问完后,释放  
  35.                           
  36.                          System.out.println("线程" + Thread.currentThread().getName() +     
  37.                                  "已离开,当前有" + (3-sp.availablePermits()) + "个并发");    
  38.                     } catch (InterruptedException e) {  
  39.                     }  
  40.                 }  
  41.             };  
  42.             exec.execute(rb);  
  43.         }  
  44.   
  45.         // 退出线程池  
  46.         exec.shutdown();  
  47.     }  
  48. }  
package tags;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import

java.util.concurrent.Semaphore;

public class TestSemaphore {

	public static void	main(String[] args) {

		ExecutorService exec = Executors.newCachedThreadPool();

		// 只能5个线程同时访问
		final Semaphore sp = new	Semaphore(3);

		// 模拟10个客户端访问
		for (int index = 0; index < 7; index++) {
			Runnable rb = new Runnable() {
				public void run() {
					try {
						sp.acquire(); // 获取许可
						
						System.out.println("线程" + Thread.currentThread().getName() +   
	                            "进入,当前已有" + (3-sp.availablePermits()) + "个并发");  
							//availablePermits()  返回此信号量中当前可用的许可数。
						
						Thread.sleep((long) (Math.random() * 10000));						
						System.out.println("线程" + Thread.currentThread().getName() + "即将离开"); 
						
						sp.release();// 访问完后,释放
						
						 System.out.println("线程" + Thread.currentThread().getName() +   
			                     "已离开,当前有" + (3-sp.availablePermits()) + "个并发");  
					} catch (InterruptedException e) {
					}
				}
			};
			exec.execute(rb);
		}

		// 退出线程池
		exec.shutdown();
	}
}

  结果:

 

线程pool-1-thread-2进入,当前已有2个并发

线程pool-1-thread-3进入,当前已有3个并发

线程pool-1-thread-1进入,当前已有2个并发

线程pool-1-thread-3即将离开

线程pool-1-thread-4进入,当前已有3个并发

线程pool-1-thread-3已离开,当前有3个并发

线程pool-1-thread-2即将离开

线程pool-1-thread-2已离开,当前有2个并发

线程pool-1-thread-7进入,当前已有3个并发

线程pool-1-thread-1即将离开

线程pool-1-thread-5进入,当前已有3个并发

线程pool-1-thread-1已离开,当前有3个并发

线程pool-1-thread-4即将离开

线程pool-1-thread-4已离开,当前有2个并发

线程pool-1-thread-6进入,当前已有3个并发

线程pool-1-thread-7即将离开

线程pool-1-thread-7已离开,当前有2个并发

线程pool-1-thread-6即将离开

线程pool-1-thread-6已离开,当前有1个并发

线程pool-1-thread-5即将离开

线程pool-1-thread-5已离开,当前有0个并发

 

参考:http://blog.csdn.net/lb85858585/article/details/7273561

JDK:http://www.cjsdn.net/doc/jdk50/java/util/concurrent/Semaphore.html#availablePermits()

 

转载自:http://uule.iteye.com/blog/1539813

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值