欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JavaSE(27)——并发工具类

程序员文章站 2024-01-13 19:38:58
...

并发工具类

java为开发者提供了三个同步工具类,说白了就是为了能够更好控制线程之间的通讯问题

  • CountDownLatch (闭锁)
  • CyclicBarrier (栅栏)
  • Semaphore (信号量)

1. CountDownLatch

CountDownLatch是一个同步的辅助类,允许一个或多个线程一直等待直到其他线程完成他们的操作

常用的API有两个:await()countDown()

  • count初始化CountDownLatch,然后需要等待的线程调用await方法。await方法会一直受阻塞直到count = 0。而其他线程完成自己的操作后,调用 countDown 使计数器count减1。当count减到0时,所有在等待的线程均会被释放
  • 原理就是通过count变量来控制等待,如果count值为0(其他线程的任务都完成了),那就可以继续执行。

举例:

public static void main(String[] args) throws InterruptedException {

    final int threadNum = 2;

    CountDownLatch latch = new CountDownLatch(threadNum);

    new Thread(() -> {
        System.out.println("线程1开始运行");
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程1继续运行");
    }).start();

    new Thread(() -> {
        System.out.println("线程2开始运行");
        try {
            Thread.sleep(2000);
            latch.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程2继续运行");
    }).start();


    new Thread(() -> {
        System.out.println("线程3开始运行");
        try {
            Thread.sleep(5000);
            latch.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程3继续运行");
    }).start();

}

public static void out(int threadNum){
    System.out.println("threadNum==="+threadNum);
}

2. CyclicBarrier

CyclicBarrier允许一组线程互动等待,等待到达某个公共屏障点。叫做cyclic是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。

也就是说,当CyclicBarrier的parties全部await()之后,才可以继续往下运行。

举例:

public static void main(String[] args) throws InterruptedException {

    final int threadNum = 5;

    CyclicBarrier cyclicBarrier = new CyclicBarrier(threadNum);

    for (int i = 0; i < threadNum; i++) {
        final int thread = i;
        new Thread(() -> {
            try {
                Thread.sleep(thread*1000);
                System.out.println("线程"+thread+"已准备就绪");
                cyclicBarrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("线程"+thread+"开始运行");
        }).start();
    }
}

3. Semaphore

Semaphore实际上就是可以控制同时访问同一的线程的个数,它维护了一组**“许可”**

  • 当调用acquire()方法时,会消费一个许可证。如果没有许可证了,会阻塞起来
    • acquire(int permits) :一次消费permits个许可证
  • 当调用tryAcquire()方法时,会尝试获取一个许可证,如果没有许可证,不会阻塞,只返回false。
    • tryAcquire(int permits):一次获取permits个许可证
    • tryAcquire(long timeout, TimeUnit unit):允许等待timeout时间后再返回false
    • tryAcquire(int permits, long timeout, TimeUnit unit):前两种方法的结合
  • 当调用release()方法时,会添加一个许可证
  • 这些许可证的数量就是一个count变量

举例:

public static void main(String[] args) throws InterruptedException {

    final int threadNum = 5;

    final int once = 2;

    Semaphore semaphore = new Semaphore(threadNum*once);

    for (int i = 0; i < 20; i++) {
        final int thread = i;
        new Thread(() -> {
            try {
                System.out.println("线程"+thread+"正在等待许可");
                semaphore.acquire(once);
                System.out.println("线程"+thread+"开始运行");
                Thread.sleep(1000);
                semaphore.release(once);
                System.out.println("线程"+thread+"执行完毕");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }
}

4. 总结

Java为我们提供了三个同步工具类

  • CountDownLatch(闭锁)

    • 某个线程等待其他线程执行完毕后,它才执行(其他线程等待某个线程执行完毕后,它才执行)
  • CyclicBarrier(栅栏)

    • 一组线程互相等待至某个状态,这组线程再同时执行。
  • Semaphore(信号量)

    • 控制一组线程同时执行
相关标签: java java