信号量Semaphore,读写锁ReadWriteLock,计数器CountDownLatch,循环栅栏CyclicBarrier运用

1.信号量Semaphore: 像synchronized, ReentrantLock等这些对临界区资源进行同步后,所有对临界区资源进行访问的线程都得串行排队,而信号量允许指定的线程数同时进行访问

demo:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class TestSemaphore implements Runnable{
    private static Semaphore semaphore = new Semaphore(5); //允许同时5个线程进行访问 不会阻塞

    @Override
    public void run(){
        try {
            semaphore.acquire();
            System.out.println(System.currentTimeMillis() +"    "+ Thread.currentThread().getName());
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            semaphore.release();
        }
    }

    public static void main(String[] args){
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        TestSemaphore testSEmaphore = new TestSemaphore();
        for(int i = 0; i < 20; i++){
            executorService.submit(testSEmaphore);
        }
        executorService.shutdown();  //关闭连接池  否则程序不会退出
    }
}

结果显示:

1578281162342    pool-1-thread-1
1578281162342    pool-1-thread-5
1578281162352    pool-1-thread-4
1578281162352    pool-1-thread-8
1578281162352    pool-1-thread-2
1578281165347    pool-1-thread-3
1578281165347    pool-1-thread-10
1578281165357    pool-1-thread-9
1578281165357    pool-1-thread-6
1578281165357    pool-1-thread-7
1578281168351    pool-1-thread-12
1578281168351    pool-1-thread-11
1578281168361    pool-1-thread-13
1578281168361    pool-1-thread-14
1578281168361    pool-1-thread-15
1578281171354    pool-1-thread-16
1578281171354    pool-1-thread-17
1578281171364    pool-1-thread-18
1578281171364    pool-1-thread-19
1578281171364    pool-1-thread-20

可以发现: 五个线程一波,分批次进行

2.读写锁 ReadWriteLock:  特点 : 对同一临界区资源进行访问的线程.如果已经有写线程占用锁,读线程和写线程需要等待;如果有读线程占有锁,写线程需要等待,读线程不需要等待

demo:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TestReadWriteLock{
    static ReentrantLock lock  = new ReentrantLock();
    static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    static ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();        //可以看出  读锁  是 读写锁内部的锁
    static ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();     //可以看出  写锁  是  读写锁内部的锁
    static int i;


    private void handleRead(Lock lock){
        lock.lock();
        try {

            System.out.println(System.currentTimeMillis() +"    "+ Thread.currentThread().getName()+ "  " + i);
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }

    private void handleWrite(Lock lock, int i){
        lock.lock();
        try {

            this.i = i;
            System.out.println(System.currentTimeMillis() + "   " + Thread.currentThread().getName());
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }

    public static void main(String[] args){
     TestReadWriteLock testReadWriteLock = new TestReadWriteLock();

        for(int i = 0; i < 18; i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    testReadWriteLock.handleRead(readLock);
                   // testReadWriteLock.handleRead(lock);
                }
            }).start();
        }

        for(int i = 18; i < 20; i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    testReadWriteLock.handleWrite(writeLock, 10);
                    //  testReadWriteLock.handleWrite(lock, 10);
                }
            }).start();
        }
    }
}

结果显示:

1578294290002    Thread-2  0
1578294290005    Thread-9  0
1578294290005    Thread-0  0
1578294290005    Thread-10  0
1578294290005    Thread-4  0
1578294290006    Thread-1  0
1578294290006    Thread-15  0
1578294290007    Thread-3  0
1578294290007    Thread-6  0
1578294290007    Thread-7  0
1578294290007    Thread-11  0
1578294290009    Thread-8  0
1578294290010    Thread-12  0
1578294290010    Thread-13  0
1578294290010    Thread-5  0
1578294290011    Thread-16  0
1578294290012    Thread-17  0
1578294290012    Thread-14  0
1578294293012   Thread-19
1578294295012   Thread-18

可以看出 读线程 运行的很快,没有停顿;最后两个线程的出现都会停顿两秒再显示

3.计数器CountDownLatch:

计数器会指定线程数量num,程序会等待num个线程都执行完成才往下继续执行 .否则调用await方法的线程一直等待.(对于num,一个线程调用countDown() 方法num次也行,因为countDown()不会阻塞线程)

demo:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestCountDownLatch{
    private  static CountDownLatch countDownLatch = new CountDownLatch(2);  //计数器指定数量


    private static class WorkThread implements Runnable{

        @Override
        public void run(){
            try {
                Thread.sleep(1000);
                System.out.println("hard working...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            countDownLatch.countDown();  //该程序完成
        }
    }

    private static class StudyThread implements Runnable{
        @Override
        public void run(){
            try {
                Thread.sleep(1000);
                System.out.println("hard study ....");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            countDownLatch.countDown();     //该程序完成
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        executorService.submit(new WorkThread());
        executorService.submit(new StudyThread());
        countDownLatch.await();     //开始等待
        System.out.println("走向人生巅峰...");
        executorService.shutdown();
    }
}

结果显示:

hard working...
hard study ....
走向人生巅峰...

如果计数器指定的个数大于2,则一直等待下去;如果小于0,运行会抛出;如果等于1,则一个线程结束主线程就执行

如果调用countDown()方法的线程数少于CountDownLatch设置的线程数,则线程调用者会一直等待;

如果调用countDown()方法的线程数大于CountDownLatch设置的线程数,多余的线程不会造成影响;CountDownLatch只要满足所设置的线程数就会继续执行.

如果其中一个发生中断异常,不会对其他线程造成影响

4.循环栅栏CycliBarrier:

循环栅栏,顾名思义就是障碍物.所有共用这个栅栏中的每个线程都得等待,知道所有线程都等待,则往下执行;循环栅栏可以多次使用

demo:

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class TestCyclicBarrier implements Runnable{
    private static CyclicBarrier cyclicBarrier;
    private static String msg;

    public TestCyclicBarrier (CyclicBarrier cyclicBarrier){
        this.cyclicBarrier = cyclicBarrier;
    }
    @Override
    public void run(){
        try {
            cyclicBarrier.await();          //每个线程在此都会等待  除非所有线程(循环栅栏规定的数量)都到了这里  则运行BarrierRun
            System.out.println(Thread.currentThread().getName() + "干活中....");
            cyclicBarrier.await();          //每个程序员干完活  在此等待 每个程序员都干完活  则运行BarrierRun
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();        //如有一个线程发生异常或者中断 抛出错误之后  其他线程就会发生此异常
        }
    }

    private static class BarrierRun implements Runnable{

        @Override
        public void run(){
            if("0".equals(msg)){
                System.out.println("所有程序员都干完活了");
            }else{
               System.out.println("所有程序员集合完毕");
               msg = "0";
            }
        }

    }

    public static void main(String[] args){
        CyclicBarrier cyclicBarrier = new CyclicBarrier(10, new BarrierRun());
        for(int i = 0; i < 10; i++){
            System.out.println("程序员" + i + "集合");
            new Thread(new TestCyclicBarrier(cyclicBarrier)).start();
        }
    }
}

结果显示:

程序员0集合
程序员1集合
程序员2集合
程序员3集合
程序员4集合
程序员5集合
程序员6集合
程序员7集合
程序员8集合
程序员9集合
所有程序员集合完毕
Thread-8干活中....
Thread-0干活中....
Thread-2干活中....
Thread-9干活中....
Thread-3干活中....
Thread-6干活中....
Thread-4干活中....
Thread-1干活中....
Thread-5干活中....
Thread-7干活中....
所有程序员都干完活了
 

如果调用await()方法的线程大于cyclicBarrier设置的线程,多余的线程可能会一直等待;

如果调用await()方法的线程少于cyclicBarrier设置的线程,调用await()方法的线程会发生一直等待

如果其中一个发生中断异常,其他线程会出现brokenException异常

---- 来源于Java高并发程序设计

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值