并发类Semaphore的使用及常用API

1.Semaphore类介绍

Semaphore类是java\util\concurrent包下用于限制线程并发数量的操作类,如果不限制并发线程的数量,CPU资源将会很快耗尽,每个线程的执行时间将会非常缓慢,因为CPU要把时间片分给不同的线程对象,而且上下文切换也需要消耗时间,最终导致系统运行效率的低下,因此限制线程的并发数量非常有必要。

2.Semaphore类实现线程的同步

2.1 多线程中的同步概念:其实就是排着队执行一个任务,执行任务是一个一个执行,并不能并行执行,这样的优点有助于业务逻辑的正确性,不会出现线程安全的问题,保证软件系统功能上的正确性。

2.2 Semaphore类的初始化许可定为1,每次消费许可也是1,消费完之后没有可用许可,则其他线程需要等待,实现了线程的同步。

2.3示例代码

public class SemaphoreDemo {

    //服务类
    public class Service{
        //初始化许可数量是1
        Semaphore semaphore = new Semaphore(1);
        public void serviceMethod(){
            try {
                //获取许可,1是获取许可数量,permits不输入默认是1
                //初始化许可数量是1,本次消费完许可之后无可用许可,则其他线程需要继续等待许可释放,实现同步
                semaphore.acquire(1);
                System.out.println(Thread.currentThread().getName()+"获取了许可,时间"+System.currentTimeMillis());
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                System.out.println(Thread.currentThread().getName()+"释放了许可,时间"+System.currentTimeMillis());
                //释放许可
                semaphore.release(1);
            }
        }
    }

    //线程类
    public class MyThread extends Thread{
        private Service service;
        public MyThread(String name, Service service) {
            super(name);
            this.service = service;
        }

        @Override
        public void run() {
            //多线程请求serviceMethod
            service.serviceMethod();
        }
    }

    //业务代码
    public static void main(String[] args) {
        SemaphoreDemo semaphoreDemo = new SemaphoreDemo();
        Service service = semaphoreDemo.new Service();
        MyThread[] myThreads = new MyThread[5];
        for(int i = 0; i<5; i++){
            MyThread myThread = semaphoreDemo.new MyThread("线程"+(i+1) , service);
            myThreads[i] = myThread;
        }
        for(MyThread myThread : myThreads){
            myThread.start();
        }
    }
}

3.Semaphore类构造方法

Semaphore(int permits) 方法,permits是允许线程获取的许可数。
Semaphore(int permits, boolean fair)方法,permits是允许线程获取的许可数,fair参数是设置是否为公平信号量,true表示公平信号量,线程启动顺序跟获取许可的顺序一致,该参数不传,默认是创建非公平信号量。

4.Semaphore类acquire(int permits)方法, release(int permits)方法及动态添加许可量

4.1 acquire(int permits)方法的作用是每调用一次acquire方法,就使用permits个许可。不传参默认使用1个许可。

4.2 release(int permits)方法的作用是没调用一次release方法,就释放release个许可。不传参默认释放1个许可。

4.3 availablePermits()方法是获取当前可用的permits许可数量(未被消费的许可数量)。
public static void main(String[] args) {
        try {
            Semaphore semaphore = new Semaphore(10);
            semaphore.acquire(2);
            System.out.println("消费2个许可,还剩可用许可个数:"+semaphore.availablePermits());
            semaphore.acquire(2);
            semaphore.acquire(2);
            semaphore.acquire(2);
            semaphore.acquire(2);
            System.out.println("消费10个许可,还剩可用许可个数:"+semaphore.availablePermits());
            semaphore.release(4);
            System.out.println("释放4个许可,还剩可用许可个数:"+semaphore.availablePermits());
            semaphore.release(4);
            semaphore.release(4);
            System.out.println("释放12个许可,还剩可用许可个数:"+semaphore.availablePermits());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
消费2个许可,还剩可用许可个数:8
消费10个许可,还剩可用许可个数:0
释放4个许可,还剩可用许可个数:4
释放12个许可,还剩可用许可个数:12

4.4 总结:初始化时定义了10个许可量,最终释放了12个个许可量,可用许可量变为了12,由此可见,new Semaphore(10)中10并不是最终的许可量,而是初始化的许可量,是可以动态变更的。

5.Semaphore类acquireUninterruptibly()方法

5.1 acquireUninterruptibly()方法是使等待获取许可的线程无法中断,不传参默认是获取1个许可
5.2 void acquireUninterruptibly(int permits)是其重载方法,permits是设置消费的许可数量,同样等待获取许可的过程中不允许被消费

5.3 acquire()等待获取许可的过程中可以被中断的示例:线程被中断

public class SemaphoreDemo {
    //服务类
    public class Service{
        //初始化许可数量是1
        Semaphore semaphore = new Semaphore(4,true);
        public void serviceMethod(){
            try {
                //获取许可,1是获取许可数量,permits不输入默认是1
                //初始化许可数量是1,本次消费完许可之后无可用许可,则其他线程需要继续等待许可释放,实现同步
                semaphore.acquire(2);
                System.out.println(Thread.currentThread().getName()+"获取了许可,时间"+System.currentTimeMillis());
                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName()+"释放了许可,时间"+System.currentTimeMillis());
                //释放许可
                semaphore.release(2);
            } catch (InterruptedException e) {
                System.out.println("捕获到了"+Thread.currentThread().getName()+"的异常"+e.getMessage());
                e.printStackTrace();
            }
        }
    }

    //线程类
    public class MyThread extends Thread{
        private Service service;
        public MyThread(String name, Service service) {
            super(name);
            this.service = service;
        }

        @Override
        public void run() {
            //多线程请求serviceMethods
            service.serviceMethod();
        }
    }

    //业务代码
    public static void main(String[] args) {
        SemaphoreDemo semaphoreDemo = new SemaphoreDemo();
        Service service = semaphoreDemo.new Service();
        MyThread[] myThreads = new MyThread[2];
        for(int i = 0; i<2; i++){
            MyThread myThread = semaphoreDemo.new MyThread("线程"+(i+1) , service);
            myThreads[i] = myThread;
        }
        for(MyThread myThread : myThreads){
            myThread.start();
        }
        myThreads[1].interrupt();
        System.out.println(myThreads[1].getName()+"线程执行了中断");
    }
}
线程1获取了许可,时间1594285214191
线程2线程执行了中断
java.lang.InterruptedException
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1302)
	at java.util.concurrent.Semaphore.acquire(Semaphore.java:467)
	at com.minxl.demo.multiThread.SemaphoreDemo$Service.serviceMethod(SemaphoreDemo.java:19)
	at com.minxl.demo.multiThread.SemaphoreDemo$MyThread.run(SemaphoreDemo.java:43)
捕获到了线程2的异常null
线程1释放了许可,时间1594285217194

5.4 acquireUninterruptibly()等待获取许可的过程中不可以被中断的示例:

public class SemaphoreDemo {
    //服务类
    public class Service{
        //初始化许可数量是1
        Semaphore semaphore = new Semaphore(2,true);
        public void serviceMethod(){
            try {
                //获取许可,1是获取许可数量,permits不输入默认是1
                //初始化许可数量是1,本次消费完许可之后无可用许可,则其他线程需要继续等待许可释放,实现同步
                semaphore.acquireUninterruptibly(2);
                System.out.println(Thread.currentThread().getName()+"获取了许可,时间"+System.currentTimeMillis());
                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName()+"释放了许可,时间"+System.currentTimeMillis());
                //释放许可
                semaphore.release(2);
            } catch (InterruptedException e) {
                System.out.println("捕获到了"+Thread.currentThread().getName()+"的异常"+e.getMessage());
                e.printStackTrace();
            }
        }
    }

    //线程类
    public class MyThread extends Thread{
        private Service service;
        public MyThread(String name, Service service) {
            super(name);
            this.service = service;
        }

        @Override
        public void run() {
            //多线程请求serviceMethods
            service.serviceMethod();
        }
    }

    //业务代码
    public static void main(String[] args) {
        SemaphoreDemo semaphoreDemo = new SemaphoreDemo();
        Service service = semaphoreDemo.new Service();
        MyThread[] myThreads = new MyThread[2];
        for(int i = 0; i<2; i++){
            MyThread myThread = semaphoreDemo.new MyThread("线程"+(i+1) , service);
            myThreads[i] = myThread;
        }
        for(MyThread myThread : myThreads){
            myThread.start();
        }
        myThreads[1].interrupt();
        System.out.println(myThreads[1].getName()+"线程执行了中断");
    }
}
线程1获取了许可,时间1594285457752
线程2线程执行了中断
线程1释放了许可,时间1594285460755
线程2获取了许可,时间1594285460755
捕获到了线程2的异常sleep interrupted
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.minxl.demo.multiThread.SemaphoreDemo$Service.serviceMethod(SemaphoreDemo.java:20)
	at com.minxl.demo.multiThread.SemaphoreDemo$MyThread.run(SemaphoreDemo.java:42)

上面代码可知,即使中断了线程,依然会继续等待获取许可,上面异常是因为sleep导致的,sleep模拟的是代码执行时间,不需要关注此异常。

6.Semaphore类availablePermits()方法与drainPermits方法

6.1 两个方法都是返回当前可用的许可数。
6.2 int availablePermits()返回Semaphore对象的当前可用的许可数,此方法经常用于调试。
6.3 int drainPermits()方法获取并立即返回当前可用的许可数,并将可用许可置为0.

7.Semaphore类getQueueLength()方法与hasQueuedThreads方法

7.1 int getQueueLength()方法是取得等待当前Semaphore对象许可的线程数。
7.2 boolean hasQueuedThreads()方法是判断有没有线程等待当前Semaphore对象的许可

8.Semaphore类tryAcquire()方法

8.1 无参tryAcquire()方法作用是尝试获取1个许可,如果获取不到返回false,此方法通常与if语句结合使用,其具有无阻塞特点。
无阻塞特点可以使线程不至于在同步地方一直等待下去,if语句不成立执行else,程序依然会继续执行。
public class SemaphoreDemo {
    //服务类
    public class Service{
        //初始化许可数量是1
        Semaphore semaphore = new Semaphore(1,true);
        public void serviceMethod(){
            try {
                //tryAcquire方法尝试获取许可
                if(semaphore.tryAcquire()){
                    System.out.println(Thread.currentThread().getName()+"获取了许可,时间"+System.currentTimeMillis());
                    Thread.sleep(3000);
                    System.out.println(Thread.currentThread().getName()+"释放了许可,时间"+System.currentTimeMillis());
                    //释放许可
                    semaphore.release(2);
                }else{
                    System.out.println(Thread.currentThread().getName()+"没有获取到许可,时间"+System.currentTimeMillis());
                }
            } catch (InterruptedException e) {
                System.out.println("捕获到了"+Thread.currentThread().getName()+"的异常"+e.getMessage());
                e.printStackTrace();
            }
        }
    }

    //线程类
    public class MyThread extends Thread{
        private Service service;
        public MyThread(String name, Service service) {
            super(name);
            this.service = service;
        }

        @Override
        public void run() {
            //多线程请求serviceMethods
            service.serviceMethod();
        }
    }

    //业务代码
    public static void main(String[] args) {
        SemaphoreDemo semaphoreDemo = new SemaphoreDemo();
        Service service = semaphoreDemo.new Service();
        MyThread[] myThreads = new MyThread[2];
        for(int i = 0; i<2; i++){
            MyThread myThread = semaphoreDemo.new MyThread("线程"+(i+1) , service);
            myThreads[i] = myThread;
        }
        for(MyThread myThread : myThreads){
            myThread.start();
        }
    }
}

线程2获取了许可,时间1594308915018
线程1没有获取到许可,时间1594308915018
线程2释放了许可,时间1594308918019

9.Semaphore类tryAcquire()的多个重载方法

9.1 boolean tryAcquire(int permits)方法是尝试获取permits个许可,获取不到返回false.

9.2 boolean tryAcquire(long timeout, TimeUnit unit)方法是在指定timeout时间内,尝试获取1个许可,获取不到返回false.

9.3 boolean tryAcquire(int permits, long timeout, TimeUnit unit)方法是在指定timeout时间内,尝试获取permits个许可,获取不到返回false.

10.Semaphore类实现多进路—多处理—多出路实验

也就是允许多个线程同时处理任务,各自处理各自任务。很简单使用acquire就可以实现

public class SemaphoreDemo {
    //服务类
    public class Service{
        //初始化许可数量是1
        Semaphore semaphore = new Semaphore(3);
        public void serviceMethod(){
            try {
                //acquire获取许可
                semaphore.acquire();
                System.out.println(Thread.currentThread().getName()+"获取了许可----开始执行任务----时间"+System.currentTimeMillis());
                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName()+"释放了许可----结束任务执行----时间"+System.currentTimeMillis());
                //release释放许可
                semaphore.release();
            } catch (InterruptedException e) {
                System.out.println("捕获到了"+Thread.currentThread().getName()+"的异常"+e.getMessage());
                e.printStackTrace();
            }
        }
    }

    //线程类
    public class MyThread extends Thread{
        private Service service;
        public MyThread(String name, Service service) {
            super(name);
            this.service = service;
        }

        @Override
        public void run() {
            //多线程请求serviceMethods
            service.serviceMethod();
        }
    }

    //业务代码
    public static void main(String[] args) {
        SemaphoreDemo semaphoreDemo = new SemaphoreDemo();
        Service service = semaphoreDemo.new Service();
        MyThread[] myThreads = new MyThread[10];
        for(int i = 0; i < myThreads.length; i++){
            MyThread myThread = semaphoreDemo.new MyThread("线程"+(i+1) , service);
            myThreads[i] = myThread;
        }
        for(MyThread myThread : myThreads){
            myThread.start();
        }
    }
}
线程3获取了许可----开始执行任务----时间1594309898741
线程1获取了许可----开始执行任务----时间1594309898741
线程2获取了许可----开始执行任务----时间1594309898741
线程2释放了许可----结束任务执行----时间1594309901743
线程3释放了许可----结束任务执行----时间1594309901743
线程1释放了许可----结束任务执行----时间1594309901743
线程5获取了许可----开始执行任务----时间1594309901743
线程4获取了许可----开始执行任务----时间1594309901743
线程8获取了许可----开始执行任务----时间1594309901743
线程5释放了许可----结束任务执行----时间1594309904743
线程6获取了许可----开始执行任务----时间1594309904743
线程4释放了许可----结束任务执行----时间1594309904744
线程8释放了许可----结束任务执行----时间1594309904744
线程9获取了许可----开始执行任务----时间1594309904744
线程7获取了许可----开始执行任务----时间1594309904744
线程6释放了许可----结束任务执行----时间1594309907744
线程10获取了许可----开始执行任务----时间1594309907744
线程7释放了许可----结束任务执行----时间1594309907745
线程9释放了许可----结束任务执行----时间1594309907745
线程10释放了许可----结束任务执行----时间1594309910744

11.Semaphore类实现多进路—单处理—多出路实验

本实验允许多个线程同时处理任务,但是执行任务的顺序是同步的,也就是执行任务的代码堵塞,单处理。使用Semaphore和ReentrantLock 实现。

public class SemaphoreDemo {
    //服务类
    public class Service{
        //初始化许可数量是3
        Semaphore semaphore = new Semaphore(3);
        //定义锁
        ReentrantLock lock = new ReentrantLock();
        public void serviceMethod(){
            try {
                //acquire获取许可,允许多个线程同时获取许可,多进路
                semaphore.acquire();
                System.out.println(Thread.currentThread().getName()+"获取了许可----时间"+System.currentTimeMillis());
                //业务代码加锁,堵塞,单处理
                lock.lock();
                System.out.println(Thread.currentThread().getName()+"开始执行任务----时间"+System.currentTimeMillis());
                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName()+"结束任务执行----时间"+System.currentTimeMillis());
                //业务代码执行完毕,释放锁
                lock.unlock();
                System.out.println(Thread.currentThread().getName()+"释放了许可----时间"+System.currentTimeMillis());
                //release释放许可,允许多个线程同时释放许可,多出路
                semaphore.release();
            } catch (InterruptedException e) {
                System.out.println("捕获到了"+Thread.currentThread().getName()+"的异常"+e.getMessage());
                e.printStackTrace();
            }
        }
    }

    //线程类
    public class MyThread extends Thread{
        private Service service;
        public MyThread(String name, Service service) {
            super(name);
            this.service = service;
        }

        @Override
        public void run() {
            //多线程请求serviceMethods
            service.serviceMethod();
        }
    }

    //业务代码
    public static void main(String[] args) {
        SemaphoreDemo semaphoreDemo = new SemaphoreDemo();
        Service service = semaphoreDemo.new Service();
        MyThread[] myThreads = new MyThread[6];
        for(int i = 0; i < myThreads.length; i++){
            MyThread myThread = semaphoreDemo.new MyThread("线程"+(i+1) , service);
            myThreads[i] = myThread;
        }
        for(MyThread myThread : myThreads){
            myThread.start();
        }
    }
}
线程3获取了许可----时间1594310311982
线程1获取了许可----时间1594310311982
线程4获取了许可----时间1594310311982
线程3开始执行任务----时间1594310311983
线程3结束任务执行----时间1594310314984
线程3释放了许可----时间1594310314984
线程1开始执行任务----时间1594310314984
线程2获取了许可----时间1594310314985
线程1结束任务执行----时间1594310317985
线程1释放了许可----时间1594310317985
线程4开始执行任务----时间1594310317985
线程5获取了许可----时间1594310317985
线程4结束任务执行----时间1594310320985
线程4释放了许可----时间1594310320985
线程2开始执行任务----时间1594310320985
线程6获取了许可----时间1594310320985
线程2结束任务执行----时间1594310323985
线程2释放了许可----时间1594310323985
线程5开始执行任务----时间1594310323985
线程5结束任务执行----时间1594310326986
线程5释放了许可----时间1594310326986
线程6开始执行任务----时间1594310326986
线程6结束任务执行----时间1594310329986
线程6释放了许可----时间1594310329986

12.使用Semaphore类创建字符串池

Semaphore类可以有效的对并发执行的线程数量进行控制,该功能可以应用在pool池技术中,可以设置同时访问pool池数据的线程数。
本实验的功能是同时有若干个线程访问池中的数据,但是同时只有一个线程可以取得池中的数据,使用完之后再放回池中。

public class PoolsBySemaphoreDemo {
    //pool池中的存储最大数
    private int poolMaxSize = 5;
    //最大许可数
    private Semaphore semaphore = new Semaphore(3);
    //存储池中具体的字符串
    LinkedList<String> list = new LinkedList<String>();
    //锁
    ReentrantLock lock = new ReentrantLock();
    //condition
    Condition condition = lock.newCondition();

    //构造函数,初始化pool池
    public PoolsBySemaphoreDemo() {
        super();
        for(int i = 0; i < poolMaxSize; i++){
            list.addLast("字符串"+(i+1));
        }
    }

    //pool池获取方法
    public String get(){
        String getString = null;
        try {
            //获取许可,才有机会操作下面业务代码
            //此许可不需要释放,在归还方法释放,防止在池为空时候,不停的执行下面业务代码
            semaphore.acquire();
            lock.lock();
            if(list.size() == 0){
                //池中为空,等待生产,释放锁
                condition.await();
            }else{
                //消费pool中数据
                getString = list.removeLast();
            }
            lock.unlock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return getString;
    }

    //pool池归还方法
    public void put(String putString){
        lock.lock();
        list.addFirst(putString);
        condition.signalAll();
        lock.unlock();
        //释放许可
        semaphore.release();
    }

    //线程类
    public static class MyThread extends Thread{
        private PoolsBySemaphoreDemo Listpool;
        public MyThread(String name, PoolsBySemaphoreDemo Listpool) {
            super(name);
            this.Listpool = Listpool;
        }

        @Override
        public void run() {
            //pool池取得数据
            String value = Listpool.get();
            System.out.println(Thread.currentThread().getName() + "线程取得pool中数据---" + value);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //pool池放回数据
            Listpool.put(value);
        }
    }

    //业务代码
    public static void main(String[] args) {
        PoolsBySemaphoreDemo listPool = new PoolsBySemaphoreDemo();
        MyThread[] myThreads = new MyThread[20];
        for(int i = 0; i < myThreads.length; i++){
            MyThread myThread = new MyThread("线程"+(i+1) , listPool);
            myThreads[i] = myThread;
        }
        for(MyThread myThread : myThreads){
            myThread.start();
        }
    }
}
线程3线程取得pool中数据---字符串5
线程5线程取得pool中数据---字符串4
线程4线程取得pool中数据---字符串3
线程2线程取得pool中数据---字符串2
线程6线程取得pool中数据---字符串3
线程1线程取得pool中数据---字符串1
线程7线程取得pool中数据---字符串4
线程9线程取得pool中数据---字符串1
线程8线程取得pool中数据---字符串5
线程10线程取得pool中数据---字符串2
线程12线程取得pool中数据---字符串5
线程11线程取得pool中数据---字符串3
线程14线程取得pool中数据---字符串1
线程13线程取得pool中数据---字符串4
线程15线程取得pool中数据---字符串2
线程16线程取得pool中数据---字符串3
线程17线程取得pool中数据---字符串5
线程18线程取得pool中数据---字符串4
线程19线程取得pool中数据---字符串1
线程20线程取得pool中数据---字符串2

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

本实验实现了生产者,消费者模式,还限制了生产者消费者的数量。

public class RepastService {
    //厨师数量
    volatile private Semaphore setSemaphore = new Semaphore(5);
    //就餐者数量
    volatile private Semaphore getSemaphore = new Semaphore(10);
    //锁
    volatile private ReentrantLock lock = new ReentrantLock();
    //生产者对象监视器
    volatile private Condition setCondition = lock.newCondition();
    //消费者对象监视器
    volatile private Condition getCondition = lock.newCondition();
    //餐具数,最多允许生成的数量
    volatile private Object[] producePosition = new Object[3];

    //是否全部消费完毕
    private boolean isEmpty(){
        boolean isEmpty = true;
        for(Object object : producePosition){
           if(object != null){
               isEmpty = false;
               break;
           }
        }
        return isEmpty;
    }

    //是否生产完毕
    private boolean isFull(){
        boolean isFull = true;
        for(Object object : producePosition){
            if(object == null){
                isFull = false;
                break;
            }
        }
        return isFull;
    }

    //生产方法
    public void set(){
        try {
            //获取许可
            setSemaphore.acquire();
            lock.lock();
            while (isFull()){
                //暂时不需要生产
                setCondition.await();
            }
            for(int i = 0; i < producePosition.length; i++){
                if(producePosition[i] == null){
                    producePosition[i] = "数据" + (i+1);
                    System.out.println(Thread.currentThread().getName() + "生产了" + producePosition[i]);
                    break;
                }
            }
            //唤醒消费者
            getCondition.signalAll();
            lock.unlock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //释放许可
            setSemaphore.release();
        }
    }

    //消费方法
    public void get(){
        try {
            //获取许可
            getSemaphore.acquire();
            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 (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //释放许可
            getSemaphore.release();
        }
    }

    //线程类
    public static class SetThread extends Thread{
        private RepastService repastService;
        public SetThread(String name, RepastService repastService) {
            super(name);
            this.repastService = repastService;
        }

        @Override
        public void run() {
            //多线程请求serviceMethods
            repastService.set();
        }
    }


    //线程类
    public static class GetThread extends Thread{
        private RepastService repastService;
        public GetThread(String name, RepastService repastService) {
            super(name);
            this.repastService = repastService;
        }

        @Override
        public void run() {
            //多线程请求serviceMethods
            repastService.get();
        }
    }

    //业务
    public static void main(String[] args) {
        RepastService repastService = new RepastService();
        Thread[] arrayC = new Thread[20];
        Thread[] arrayB = new Thread[20];
        for (int i = 0; i < 20; i++) {
            SetThread setThread = new SetThread("生产者线程" + (i + 1), repastService);
            arrayC[i] = setThread;
            GetThread getThread = new GetThread("消费者线程" + (i + 1), repastService);
            arrayB[i] = getThread;
        }
        for (int i = 0; i < 20; i++) {
            arrayC[i].start();
            arrayB[i].start();
        }
    }
}

14.总结

Semaphore类提供了限制并发线程数的功能,它具有synchronized所不具有的强大功能,比如等待获取许可的时间可以加入等待时间,还可以尝试是否可以持有锁等拓展功能,可以说Semaphore类是强有力的控制并发线程个数的解决方案之一。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值