java并发编程学习8--同步器--信号量

来源:互联网 发布:指定dns解析域名 编辑:程序博客网 时间:2024/05/17 23:50
【同步器    java.util.concurrent包包含几个能帮助人们管理相互合作的线程集的类。这些机制具有为线程直间的共用集结点模式提供的‘预制功能’。    如果有一个相互合作的线程满足这些行为模式之一,那么应该直接使用提供的类库而不是显示的使用锁与条件的集合。
【信号量    一个信号量管理过个许可证。为了通过信号量,线程通过调用acquire()请求许可。其实没有实际的许可对象,信号连也仅仅是维护一个计数器。    许可的数目是固定的,由此限制了线程通过的数量。当一个线程执行完之后,应该调用release()释放许可证,让其他线程有机会执行。事实上,    任意一个线程都有可以释放任意个数的许可证,这可能会增加许可证的个数。所以我建议,如果不是非常明确的知道为什么要释放多个许可证,就一定    是让获得许可证的线程是放一个许可证。
【常用方法    1.构造函数:      Semaphore(int permits):创建具有给定许可数和非公平设置的Semaphore      Semaphore(int permits,boolean fair):此类的构造方法可选地接受一个公平 参数。当设置为 false 时(默认也是false),此类不对线程获取许可的顺序做任何保证。        特别地,闯入是允许的,也就是说可以在已经等待的线程前为调用 acquire() 的线程分配一个许可,从逻辑上说,就是新线程将自己置于等待线程队列的头部。        当公平设置为 true 时,信号量保证对于任何调用获取方法的线程而言,都按照处理它们调用这些方法的顺序(即先进先出;FIFO)来选择线程、获得许可。        注意,FIFO 排序必然应用到这些方法内的指定内部执行点。所以,可能某个线程先于另一个线程调用了 acquire,但是却在该线程之后到达排序点,并且从方法返回时也类似。
  2.Semaphore还提供一些其他方法:        int availablePermits() :返回此信号量中当前可用的许可证数。        int getQueueLength():返回正在等待获取许可证的线程数。        boolean hasQueuedThreads() :是否有线程正在等待获取许可证。        void reducePermits(int reduction) :减少reduction个许可证。是个protected方法。        Collection getQueuedThreads() :返回所有等待获取许可证的线程集合。是个protected方法。【补充    当许可证的个数为1时,可以充当互斥锁使用。
【例子:只能同时有5个线程访问的信号量:
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;public class SemaTest {    public static void main(String[] args) throws InterruptedException {        // 线程池        ExecutorService exec = Executors.newFixedThreadPool(20);        // 只能5个线程同时访问        final Semaphore semp = new Semaphore(5);        // 模拟20个客户端访问        for (int index = 0; index < 20; index++) {            final int NO = index;            Runnable run = new Runnable() {                public void run() {                    try {                        //记住这里需要使用while,如果直接用if判断,那么每个线程只有一次机会去尝试占有对象                        while (1 == 1){                            // 获取许可                            if(semp.tryAcquire()) {                                System.out.println(Thread.currentThread().getName() + " 【 Access: " + NO);                                Thread.sleep(100);                                // 访问完后,释放                                semp.release();                                System.out.println(Thread.currentThread().getName() + " 【 Release: " + NO);                                System.out.println("----------------- 【 " + Thread.currentThread().getName() + "】" + semp.availablePermits());                                break;                            }else{                                System.out.println(Thread.currentThread().getName() + " 【 NOT Access: " + NO);                                Thread.sleep(100);                            }                        }                    } catch (Exception e) {                        e.printStackTrace();                    }                }            };            exec.execute(run);        }        //让子线程有充分时间运行完        Thread.sleep(1000);        exec.shutdown();    }}

可能的结果:
 
原创粉丝点击