21.Semaphore信号量

Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。它的用法如下:

  • availablePermits() //用来获取当前可用的资源数量
  • wc.acquire(); //申请资源
  • wc.release();// 释放资源
import java.util.Random;
import java.util.concurrent.Semaphore;

public class SemaphoreDemo implements Runnable{
    private String name;
    private Semaphore semaphore;

    public SemaphoreDemo(String name, Semaphore semaphore) {
        this.name = name;
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            //剩余的资源
            int i = semaphore.availablePermits();
            if (i > 0){
                System.out.println(name+" 有资源了");
            }else {
                System.out.println(name+" 没资源了");
            }
            semaphore.acquire();
            System.out.println(name+"资源到手");
            Thread.sleep(new Random().nextInt(1000));
            System.out.println(name+"好!!!");
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args){
        Semaphore semaphore = new Semaphore(3);
        for (int i = 1; i <= 5; i++) {
            SemaphoreDemo demo = new SemaphoreDemo("第"+i+"个",semaphore);
            new Thread(demo).start();
        }
    }
    //第1个 有资源了
    //第1个资源到手
    //第2个 有资源了
    //第2个资源到手
    //第3个 有资源了
    //第3个资源到手
    //第4个 没资源了
    //第5个 没资源了
    //第2个好!!!
    //第4个资源到手
    //第1个好!!!
    //第5个资源到手
    //第3个好!!!
    //第4个好!!!
    //第5个好!!!
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 信号量:允许多个线程同时访问
 * public  Semaphore(int permits)
 * public Semaphore(int permits,boolean fair) //第二参数可以指定是否公平
 */
public class SemapDemo implements Runnable{
    final Semaphore semaphore = new Semaphore(5);//指定信号量的准入数
    @Override
    public void run() {
        try {
            semaphore.acquire();//尝试获取一个准入的许可,若无法获得,则线程会等待,直到有线程释放一个许可或当前线程被中断
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getId()+":done");
            semaphore.release();//线程访问资源结束后,释放一个许可
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args){
        //线程池
        ExecutorService exec = Executors.newFixedThreadPool(20);
        final SemapDemo demo = new SemapDemo();
        for (int i = 0; i < 20; i++) {
            exec.submit(demo);
        }
    }
    //同时开启20个线程,系统以5个线程一组为单位,依次输出带有线程ID的提示文本
}
posted @ 2019-08-23 15:38  fly_bk  阅读(178)  评论(0编辑  收藏  举报