Java multithreading-concurrent containers and tools

Three, concurrent containers and tools

1. Concurrent containers

【1】ConcurrentHashMap

HashMap in the case of multithreading. Note that neither KEY nor VALUE can be null

【2】 ConcurrentSkipListMap

TreeMap in multithreading

ConcurrentSkipListMap<String, Integer> concurrentSkipListMap = new ConcurrentSkipListMap<String, Integer>();
concurrentSkipListMap.put("a", 1);
concurrentSkipListMap.put("A", 2);
concurrentSkipListMap.put("0", 3);
concurrentSkipListMap.put("b", 4);
System.out.println(concurrentSkipListMap); // {0=3, A=2, a=1, b=4}

System.out.println("0-" + (int)'0'); // 0-48
System.out.println("A-" + (int)'A'); // A-65
System.out.println("a-" + (int)'a'); // a-97
System.out.println("b-" + (int)'b'); // b-98

【3】ConcurrentSkipListSet

TreeSet in multithreading

【4】CopyOnWriteArrayList

ArrayList in the case of multithreading. Locks for write operations and no locks for read operations to ensure performance

volatile modified Object array, every time the array is modified, a new array will be created and the reference will be pointed to it

For example addoperation:

public boolean add(E e) {
    
    
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
    
    
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1); // 创建新的数组
        newElements[len] = e;
        setArray(newElements); // 指向新的数组
        return true;
    } finally {
    
    
        lock.unlock();
    }
}

【5】CopyOnWriteArraySet

A CopyOnWriteArrayList is maintained internally

private final CopyOnWriteArrayList<E> al;

Before adding a new element, it will first determine whether the element already exists, and if it is not found, it will be saved in the container

/**
 * java.util.concurrent.CopyOnWriteArrayList#addIfAbsent(E)方法
 */
public boolean addIfAbsent(E e) {
    
    
    Object[] snapshot = getArray();
    return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
    addIfAbsent(e, snapshot);
}

2. Concurrency tools

【1】CountDownLatch

Countdown latch. Give the statistical value in advance, and subtract 1 each time, when it is reduced to 0, let go

CountDownLatch countDownLatch = new CountDownLatch(2);

new Thread(() -> {
    
    
    System.out.println("A");
    try {
    
    
        Thread.sleep(500);
    } catch (InterruptedException e) {
    
    
        e.printStackTrace();
    }
    countDownLatch.countDown(); // 减1
}).start();

new Thread(() -> {
    
    
    System.out.println("B");
    try {
    
    
        Thread.sleep(1000);
    } catch (InterruptedException e) {
    
    
        e.printStackTrace();
    }
    countDownLatch.countDown(); // 减1
}).start();

try {
    
    
    countDownLatch.await(); // Main线程等待
} catch (InterruptedException e) {
    
    
    e.printStackTrace();
}

System.out.println("结束!");

【2】CyclicBarrier

Circulation barrier. Give the statistical value in advance, add 1 each time, when the statistical value is added, let go

Use method one:

public static void main(String[] args) {
    
    
    CyclicBarrier cyclicBarrier = new CyclicBarrier(3); // 记得算上Main线程

    new Thread(() -> {
    
    
        System.out.println("A");
        try {
    
    
            Thread.sleep(500);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        try {
    
    
            cyclicBarrier.await(); // 等待(加1)
        } catch (InterruptedException | BrokenBarrierException e) {
    
    
            e.printStackTrace();
        }
    }).start();

    new Thread(() -> {
    
    
        System.out.println("B");
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        try {
    
    
            cyclicBarrier.await(); // 等待(加1)
        } catch (InterruptedException | BrokenBarrierException e) {
    
    
            e.printStackTrace();
        }
    }).start();

    try {
    
    
        cyclicBarrier.await(2, TimeUnit.SECONDS); // 只等待2秒钟(加1)
    } catch (InterruptedException | BrokenBarrierException | TimeoutException e) {
    
    
        e.printStackTrace();
    }

    System.out.println("结束!");
}

Usage 2:

CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> {
    
    
    System.out.println("结束!");
}); // 其他线程都执行完毕后,执行该线程方法

new Thread(() -> {
    
    
    System.out.println("A");
    try {
    
    
        Thread.sleep(500);
    } catch (InterruptedException e) {
    
    
        e.printStackTrace();
    }
    try {
    
    
        cyclicBarrier.await(); // 等待(加1)
    } catch (InterruptedException | BrokenBarrierException e) {
    
    
        e.printStackTrace();
    }
}).start();

new Thread(() -> {
    
    
    System.out.println("B");
    try {
    
    
        Thread.sleep(1000);
    } catch (InterruptedException e) {
    
    
        e.printStackTrace();
    }
    try {
    
    
        cyclicBarrier.await(); // 等待(加1)
    } catch (InterruptedException | BrokenBarrierException e) {
    
    
        e.printStackTrace();
    }
}).start();

【3】Semaphore

signal. Specify the number of threads allowed to execute at one time

int loop = 10;
int permits = 2;

ExecutorService executorService = Executors.newFixedThreadPool(loop);
Semaphore semaphore = new Semaphore(permits);

for (int i = 0; i < loop; i++) {
    
    
    executorService.execute(() -> {
    
    
        try {
    
    
            semaphore.acquire();
            System.out.println(Thread.currentThread().getName() + " ---> 执行任务");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            semaphore.release();
        }
    });
}

if (!executorService.isShutdown()) {
    
    
    executorService.shutdown();
}

【4】Exchanger

Exchanger. Used for data exchange between threads. If a thread initiates the exchange, it will always wait for another thread to perform the exchange. If you are afraid of waiting too long, you can use the public V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutExceptionmethod

Exchanger<String> exchanger = new Exchanger<String>();
new Thread(() -> {
    
    
    try {
    
    
        System.out.println(Thread.currentThread().getName() + "发出了消息,等待回复");

        String exchange = exchanger.exchange("hello?");
        Thread.sleep(2000);
        System.out.println(Thread.currentThread().getName() + "收到了:" + exchange);
    } catch (InterruptedException e) {
    
    
        e.printStackTrace();
    }
}, "线程A").start();

new Thread(() -> {
    
    
    try {
    
    
        Thread.sleep(3000);

        String exchange = exchanger.exchange("hi!");
        System.out.println(Thread.currentThread().getName() + "收到了:" + exchange + ",并且已回复");
    } catch (InterruptedException e) {
    
    
        e.printStackTrace();
    }
}, "线程B").start();

Guess you like

Origin blog.csdn.net/adsl624153/article/details/103865261