Semaphore:该类的主要作用是限制线程并发的数量, 为什么要限制并发的数量? 因为CPU资源有限,如果是多个线程同时运行,CPU要把时间片分配给不同的线程对象, 而且上下切换时特别耗时,最终会导致系统运行效率降低。 类Semaphore的构造方法 public Semaphore(int permits) { sync = new NonfairSync(permits); } 参数permits是允许,许可的意思,代表同一时间内, 最多允许多少个线程执行acquire()和release()之间的代码。
private Semaphore semaphore=new Semaphore(1); 表示同一时间内最多只有1个线程可以执行acquire()和release()之间的代码。
当permits大于1时,表示同一时间内,最多允许有x个线程可以执行acquire()和release()之间的代码。 当permits大于1时,该类无法保证线程安全,因为有可能出现多个线程共同访问实例变量,导致数据变脏. acquire()无参数,表示占用1个许可
acquire(int permits)有参方法,每调用1次该方法,就会使用permits个许可. release()无参数,表示增加1个许可 release(int permits)有参方法,每调用1次该方法,就会增加permits个许可.
案例代码如下:
public class Service { private Semaphore semaphore=new Semaphore(1); public void test(){ try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() +" 开始时间="+System.currentTimeMillis()); Thread.sleep(5000); System.out.println(Thread.currentThread().getName() +" 结束时间="+System.currentTimeMillis()); //System.out.println("availablePermits_"+Thread.currentThread().getName()+"="+semaphore.availablePermits()); semaphore.release(); //System.out.println("availablePermits_"+Thread.currentThread().getName()+"="+semaphore.availablePermits()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }线程类
public class Thread_A extends Thread { private Service service; public Thread_A(Service service){ super(); this.service=service; } public void run(){ service.test(); } }测试类
public class Test { public static void main(String[] args) { Service service=new Service(); Thread_A a=new Thread_A(service); a.setName("A"); Thread_B b=new Thread_B(service); b.setName("B"); Thread_C c=new Thread_C(service); c.setName("C"); a.start(); b.start(); c.start(); } }测试结果:
A 开始时间=1501977937514 A 结束时间=1501977942516 B 开始时间=1501977942516 B 结束时间=1501977947526 C 开始时间=1501977947526 C 结束时间=1501977952532改变1: acquire(int permits)有参方法,每调用1次该方法,就会使用permits个许可. 将上述案例中其他类不改变只改变Service类中下面两处: release()无参数,表示增加1个许可 release(int permits)有参方法,每调用1次该方法,就会增加permits个许可.
Semaphore semaphore=new Semaphore(3); ... semaphore.acquire(2);可得结果为:
A 开始时间=1501974670443 A 结束时间=1501974675443 B 开始时间=1501974675443 B 结束时间=1501974680443分析:
Semaphore类总共有3个许可,表示同一时间允许3个许可用在执行代码块M, 而acquire的参数为2,表示每次调用该方法就会占用2个许可, 故:3/2=1余1:表示同一时间只有1个线程执行代码块M, 所以A线程先执行,当A线程结束前,会调用release(),增加一个许可, 由于之前剩余一个许可,剩余许可加上增加的许可刚好两个许可,便执行B线程, 当B线程执行完毕时增加1个许可,但由于没有其他许可剩余,故C线程无法执行.改变2:
其他地方不变,只将Semaphore的构造参数改为4,则A、B、C线程便可全部执行 B 开始时间=1501976068531 A 开始时间=1501976068531 A 结束时间=1501976073532 B 结束时间=1501976073532 C 开始时间=1501976073532 C 结束时间=1501976078532改变3:
其他地方不变,semaphore.release(permits),permits>2,则A、B、C线程也可全部执行: A 开始时间=1501976300912 A 结束时间=1501976305922 B 开始时间=1501976305922 C 开始时间=1501976305922 B 结束时间=1501976310922 C 结束时间=1501976310922 availablePermits()可以当前可用的许可 说明:Semaphore的构造方法参数,并非是最终许可数,恰恰相反它是许可数的初始状态.欢迎关注下面二维码进行技术交流:
