juc-Semaphore信号量

Semaphore 含义是信号、信号系统。

此类的主要作用就是限制线程并发的数量。

public class Service {
    private Semaphore semaphore=new Semaphore(2);//同一时间做多允许一个线程执行
    public void testMethod(){
        try {
            semaphore.acquire();// 使用掉一个许可,减法
            System.out.println(Thread.currentThread().getName()+"begin timer="+System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println(Thread.currentThread().getName()+"end timer"+System.currentTimeMillis());
            semaphore.release();//创建一个许可
        }catch (Exception e){
            System.out.println("线程"+Thread.currentThread().getName()+"进入了catch");
            e.fillInStackTrace();
        }

    }
}
public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service){
    super();
    this.service=service;
    }

    public void run(){
        service.testMethod();
    }
}
public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service){
    super();
    this.service=service;
    }

    public void run(){
        service.testMethod();
    }
}
public class ThreadC extends Thread {
    private Service service;
    public ThreadC(Service service){
    super();
    this.service=service;
    }

    public void run(){
        service.testMethod();
    }
}

public class Run2 {
    public static void main(String[] args) throws InterruptedException {
        Service service=new Service();
        ThreadA a=new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadB b=new ThreadB(service);
        b.setName("B");
        b.start();
        Thread.sleep(1000);
        b.interrupt();//中断线程B
        System.out.println("main中断了b");
    }
}

不可中断的Semaphore–acquireUninterruptibly()

public class Service {
    private Semaphore semaphore=new Semaphore(1);
    public void testMethod(){
        semaphore.acquireUninterruptibly();// 不可中断
        System.out.println(Thread.currentThread().getName()+"begin timer="+System.currentTimeMillis());
        for (int i=0;i<Integer.MAX_VALUE/50;i++){
            String newString =new String();
            Math.random();
        }
        System.out.println(Thread.currentThread().getName()+"end timer="+System.currentTimeMillis());
        semaphore.release();
    }
}

availablePermits()返回此Semaphore对象中当前可用的许可数,

drainPermits()可获取并返回立即可用的所有许可个数,并且将可用许可置0。

public class MyService {
    private Semaphore semaphore=new Semaphore(10);
    public void testMethod(){
        try {
            semaphore.acquire();
            System.out.println(semaphore.availablePermits());//获取当前的许可数
            System.out.println(semaphore.availablePermits()+" "+semaphore.drainPermits());//获取当前许可数,并将许可数清零
            System.out.println(semaphore.availablePermits());
        }catch (Exception e){
            e.fillInStackTrace();
        }finally {
            semaphore.release();
        }
    }
}

方法getQueueLength()的作用是取得等待许可的线程个数。

方法hasQueuedThreads()的作用是判断有没有线程在等待这个许可。

public class MyService {
    private Semaphore semaphore=new Semaphore(1);
    public void testMethod(){
        try {
            semaphore.acquire();
            Thread.sleep(1000);
            System.out.println("大约还有"+semaphore.getQueueLength()+"个线程等待");
            System.out.println("是否还有线程在等待信号量呢"+semaphore.hasQueuedThreads());
        }catch (Exception e){
            e.fillInStackTrace();
        }finally {
            semaphore.release();
        }
    }
}

在这里插入图片描述

公平与非公平信号量,默认线程是公平的信号量,线程顺序执行

public class MyService {
    private Semaphore semaphore=new Semaphore(1true);//true为公平,false为不公平
    public void testMethod(){
        try {
            semaphore.acquire();
            Thread.sleep(1000);
            System.out.println("大约还有"+semaphore.getQueueLength()+"个线程等待");
            System.out.println("是否还有线程在等待信号量呢"+semaphore.hasQueuedThreads());
        }catch (Exception e){
            e.fillInStackTrace();
        }finally {
            semaphore.release();
        }
    }
}

方法tryAcquire()的使用无参方法tryAcquire()的作用是尝试地获得1个许可,如果获取不到则返回false,此方法通常与if语句结合使用,其具有无阻塞的特点。无阻塞的特点可以使线程不至于在同步处一直持续等待的状态,如果if语句判断不成立则线程会继续走else语句,程序会继续向下运行。

方法tryAcquire(int permits)的使用有参方法tryAcquire(int permits)的作用是尝试地获得x个许可,如果获取不到则返回false。

方法tryAcquire(long timeout, TimeUnit unit)的使用有参方法tryAcquire(int long timeout, TimeUnit unit)的作用是在指定的时间内尝试地获得1个许可,如果获取不到则返回false。

方法tryAcquire(int permits, long timeout,TimeUnit unit)的使用有参方法tryAcquire(int permits, long timeout, TimeUnitunit)的作用是在指定的时间内尝试地获得x个许可,如果获取不到则返回false。

使用Semaphore创建字符串池

使用Semaphore实现多生产者/多消费者模式

public class RepastService {
    volatile private Semaphore setSemaphore = new Semaphore(10);//厨师
    volatile private Semaphore getSemaphore = new Semaphore(20);//就餐者
    volatile private ReentrantLock lock = new ReentrantLock();
    volatile private Condition setCondition = lock.newCondition();
    volatile private Condition getCondition = lock.newCondition();
    //producePosition 变量含义是最多只有4个盒子存放菜品
    volatile private Object[] producePosition = new Object[4];

    private boolean isEmpty() {
        boolean isEmpty = true;
        for (int i = 0; i < producePosition.length; i++) {
            if (producePosition[i] != null) {
                isEmpty = false;
                break;
            }
        }
        if (isEmpty == true) {
            return true;
        } else {
            return false;
        }
    }

    private boolean isFull() {
        boolean isFull = true;
        for (int i = 0; i < producePosition.length; i++) {
            if (producePosition[i] == null) {
                isFull = false;
                break;
            }
        }
        return isFull;
    }

    public void set() {
        try {
            setSemaphore.acquire();
            lock.lock();
            while (!isEmpty()) {
                getCondition.await();//生产者等待
            }
            for (int i = 0; i < producePosition.length; i++) {
                if (producePosition[i] == null) {
                    producePosition[i] = "数据";
                    System.out.println(Thread.currentThread().getName() + "生产了" + producePosition[i]);
                    break;
                }
            }
            getCondition.signalAll();
            lock.unlock();
        } catch (Exception e) {
            e.fillInStackTrace();
        } finally {
            setSemaphore.release();
        }
    }

    public void get() {
        try {
            getSemaphore.acquire();//允许同时16个人就餐
            lock.lock();
            while (isEmpty()) {
                getCondition.await();
            }
            for (int i = 0; i < producePosition.length; i++) {
                if (producePosition[i] != null) {
                    System.out.println(Thread.currentThread().getName() + "消费了" + producePosition[i]);
                    producePosition[i] = null;
                    break;
                }
            }
            setCondition.signalAll();
            lock.unlock();
        } catch (Exception e) {
            e.fillInStackTrace();
        } finally {
            getSemaphore.release();
        }
    }
}
public class ThreadC extends Thread {
    private RepastService service;
    public ThreadC(RepastService service){
        super();
        this.service=service;
    }
    public void run(){
        service.get();
    }
}
public class ThreadP extends Thread {
    private RepastService service;
    public ThreadP(RepastService service){
        super();
        this.service=service;
    }
    public void run(){
        service.set();
    }
}
public class Run {
    public static void main(String[] args) throws InterruptedException {
        RepastService service=new RepastService();
        ThreadP[] arrayP=new ThreadP[60];
        ThreadC[] arrayC=new ThreadC[60];
        for (int i=0;i<60;i++){
            arrayP[i]=new ThreadP(service);
            arrayC[i]=new ThreadC(service);
        }
        Thread.sleep(2000);
        for (int i=0;i<60;i++){
            arrayP[i].start();
            arrayC[i].start();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值