关于Java并发工具,90%的程序员需要了解的那些技术栈( 二 )


public static void main(String[] args) {    Semaphore semaphore = new Semaphore(2);    ExecutorService executor = Executors.newFixedThreadPool(10);    Runnable task = () -> {        try {            System.out.println(Thread.currentThread().getName() + " acquire before");            semaphore.acquire();            System.out.println(Thread.currentThread().getName() + " acquire ok");            semaphore.release();        } catch (InterruptedException e) {            e.printStackTrace();        }    };    executor.execute(task);    executor.execute(task);    executor.execute(task);    executor.execute(task);}Exchanger 线程间交换数据Exchanger是一个用户线程间交换数据的工具类,它提供了一个同步点,在这个同步点上,两个线程可以交换彼此的数据 。这两个线程通过exchange方法交换数据,如果第一个线程先执行exchange方法,他会一直等待第二个线程也执行exchange方法,当两个线程都达到同步点时,这两个线程交换数据,将本线程产生的数据传递给对方 。
public static void main(String[] args) {    Exchanger<String> exchanger = new Exchanger<>();    Runnable task = () -> {        try {            String result = exchanger.exchange(Thread.currentThread().getName());            System.out.println(Thread.currentThread().getName() + ": " + result);        } catch (InterruptedException e) {            e.printStackTrace();        }    };    ExecutorService executor = Executors.newFixedThreadPool(2);    executor.execute(task);    executor.execute(task);}Exchanger实现分析Exchanger算法的核心是通过一个可交换数据的slot,以及一个可以带有数据item的参与者,slot是Node类型,Node定义如下:
@sun.misc.Contended static final class Node {    int index;              // Arena index    int bound;              // Last recorded value of Exchanger.bound    int collides;           // Number of CAS failures at current bound    int hash;               // Pseudo-random for spins    Object item;            // This thread's current item    volatile Object match;  // Item provided by releasing thread    volatile Thread parked; // Set to this thread when parked, else null}static final class Participant extends ThreadLocal<Node> {    public Node initialValue() { return new Node(); }}每一个参与者都带有一个Participant,当调用exchange时,如果slot为空,则将自己携带的数据CAS设置到slot上,然后park自己;如果slot不为空,则表示已经有线程在slot里设置了数据,则读取Node.item字段,并将自己携带的数据设置到Node.match字段,然后唤醒之前设置数据的线程(之前阻塞的线程在唤醒后读取Node.match字段返回),然后返回数据即可 。
小结了解了这些Java并发工具类,小伙伴们在日常开发中,都用到哪种或者哪几种呢?


推荐阅读