juc包下四大并发工具

Posted hetaoyuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了juc包下四大并发工具相关的知识,希望对你有一定的参考价值。

juc.CountDownLatch 闭锁

一个线程在等待一组线程后再恢复执行

await()等待其他线程执行完毕

被等待线程执行完毕后计数器-1

如何知道其他线程执行完了?

计数器,若一组线程为,CountDown为5,减到0代表等待线程被全部执行完毕

一次性工具:当Countdown的值减到0的时候再也无法恢复

 

juc内部的代码都是lock体系来实现的

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;


// 运动员线程
class CDLTask implements Runnable {
    private CountDownLatch countDownLatch;

    public CDLTask(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开始跑步");
        try {
            TimeUnit.SECONDS.sleep(1);
            System.out.println(Thread.currentThread().getName()+"到达终点");
            countDownLatch.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(4);
        CDLTask cdlTask = new CDLTask(countDownLatch);
        System.out.println("比赛开始...");
        new Thread(cdlTask,"运动员A").start();
        new Thread(cdlTask,"运动员B").start();
        new Thread(cdlTask,"运动员C").start();
        new Thread(cdlTask,"运动员D").start();
        // 等待所有线程都到达终点后再输出此语句
        countDownLatch.await();
        System.out.println("比赛结束...");
    }
}

技术图片

 


juc.CyclicBarrier  循环栅栏

一组线程同时到达临界点后再恢复执行(先到达临界点的线程会阻塞,直到所有线程都到达临界点)

public CyclicBarrier(int parties, Runnable barrierAction)

当多个线程同时到达临界点时,

随机挑选一个线程执行barrierAction后再同时恢复执行

计数器的值可以恢复

await

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

class CBTask implements Runnable {
    private CyclicBarrier cyclicBarrier;

    public CBTask(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+
                "正在写入数据...");
        try {
            TimeUnit.SECONDS.sleep(2);
            System.out.println(Thread.currentThread().getName()+
                    "写入数据完毕,等待其他线程写入完毕...");
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println("所有线程均已写入完毕,继续恢复执行...");
    }
}
class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(4
                ,() -> {
            System.out.println("当前线程为:"+Thread.currentThread().getName());
        });
        CBTask cbTask = new CBTask(cyclicBarrier);
        for (int i = 0; i < 4; i++) {
            new Thread(cbTask,"写线程"+(i+1)).start();
        }
    }
}

技术图片

 


juc.Exchanger 线程交换器

用于两个线程直线的数据交换,当Exchanger只有一个线程时,该线程会阻塞直到有别的线程
调用exchange进入缓冲区,当前线程与新线程交换数据后同时恢复执行。
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;


class ExchangerDemo {
    public static void main(String[] args) {
        Exchanger<String> exchanger = new Exchanger<>();
        Thread girlThread = new Thread(() -> {
            try {
                String girl = exchanger.exchange("我喜欢你.....");
                System.out.println("女生说:"+girl);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        girlThread.start();
        Thread boyThread = new Thread(() -> {
            System.out.println("女神缓缓步入眼帘...");
            try {
                TimeUnit.SECONDS.sleep(1);
                String boy = exchanger.exchange("我喜欢你!");
                System.out.println("男生说:"+boy);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        boyThread.start();
    }
}

技术图片

 



juc.Semaphore 信号量

acquire() : 尝试占用一个信号量,失败的线程会阻塞直到有新的信号量

release() : 释放一个信号量

acquire(int n) : 尝试占用n个信号量,失败的线程会阻塞直到有新的信号量

release(int n) : 释放n个信号量

 

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;


class SemaphoreTask implements Runnable {
    private Semaphore semaphore;

    public SemaphoreTask(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire(2);
            System.out.println(Thread.currentThread()
                    .getName()+"占用2台设备生产");
            TimeUnit.SECONDS.sleep(2);
            System.out.println(Thread.currentThread()
                    .getName()+"生产完毕,释放设备");
            semaphore.release(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(5);
        SemaphoreTask task = new SemaphoreTask(semaphore);
        for (int i = 0; i < 8; i++) {
            new Thread(task,"工人"+(i+1)).start();
        }
    }
}

技术图片

 

以上是关于juc包下四大并发工具的主要内容,如果未能解决你的问题,请参考以下文章

打怪升级juc关于aqs

Java并发编程 JUC中的锁

Java 语言特性——JUC(Java 并发工具包)

JUC并发编程 -- JUC介绍 & 线程/进程 & 并发/并行 & Java代码查看CPU的核数

Java 并发之 Executor 框架

一行Java代码实现游戏中交换装备