java信号量使用
在很多情况下,可能有多个线程需要访问数目很少的资源。假想在服务器上运行着若干个回答客户端请求的线程。这些线程需要连接到同一数据库,但任一时刻只能获得一定数目的数据库连接。你要怎样才能够有效地将这些固定数目的数据库连接分配给大量的线程?
给方法加锁,保证的是同一时刻只能有一个人去调用此方法,其他所有线程排队等待,即使你的数据库链接有10个,也始终只有一个处于使用状态。
信号量则能将所有数据库链接有效使用起来,下面是一个典型的使用信号量的例子:
Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。例如,下面的类使用信号量控制对内容池的访问:
这里是一个实际的情况,大家排队上厕所,厕所只有两个位置,来了10个人需要排队。
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;public class MySemaphore extends Thread {Semaphore position;private int id;public MySemaphore(int i,Semaphore s){ this.id=i; this.position=s;}public void run(){ try{ if(position.availablePermits()>0){ System.out.println("顾客["+this.id+"]进入厕所,有空位"); } else{ System.out.println("顾客["+this.id+"]进入厕所,没空位,排队"); } /* *从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。 *获取一个许可(如果提供了一个)并立即返回,将可用的许可数减 1。 *如果没有可用的许可,则在发生以下两种情况之一前,禁止将当前线程用于线程安排目的并使其处于休眠状态 */ position.acquire(); System.out.println("顾客["+this.id+"]获得坑位"); Thread.sleep((int)(Math.random()*1000)); System.out.println("顾客["+this.id+"]使用完毕"); /* * 释放一个许可,将其返回给信号量。 *释放一个许可,将可用的许可数增加 1。如果任意线程试图获取许可,则选中一个线程并将刚刚释放的许可给予它。然后针对线程安排目的启用(或再启用)该线程。 */ position.release(); } catch(Exception e){ e.printStackTrace(); }}public static void main(String args[]){ ExecutorService list=Executors.newCachedThreadPool(); Semaphore position=new Semaphore(2); for(int i=0;i<10;i++){ list.submit(new MySemaphore(i+1,position)); } list.shutdown(); position.acquireUninterruptibly(2); System.out.println("使用完毕,需要清扫了"); position.release(2);}}