Java 并发常用工具说明

来源:互联网 发布:网络云台控制软件 编辑:程序博客网 时间:2024/05/19 22:50

CountDownLatch

import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Main {    public static class SortThread implements Runnable {        private CountDownLatch latch;        private int[] datas;        private int start;        private int stop;        @Override        public void run() {            System.out.println(start + " - " + stop + "已完成排序!");            latch.countDown();        }        public SortThread(CountDownLatch latch, int[] datas, int start, int stop) {            this.latch = latch;            this.datas = datas;            this.start = start;            this.stop = stop;        }    }    public static void main(String[] args) throws InterruptedException {        ExecutorService threadPool = Executors.newFixedThreadPool(16);        int count = 10;// 分10个线程排序        /**         * 目的让多个线程达到各自状态,然后变成事件进行通知         */        final CountDownLatch latch = new CountDownLatch(count/*这里是countDown的个数*/);        int[] datas = new int[1024];        int step = datas.length / count;        for (int i = 0; i < count; i++) {            int start = i * step;            int end = (i + 1) * step;            threadPool.submit(new SortThread(latch, datas, start, end));        }        latch.await();        //合并排序的数据        System.out.println("合并数据!");        threadPool.shutdown();    }}

CyclicBarrier

import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Main {    public static class SortThread implements Runnable {        private CyclicBarrier barrier;        private int[] datas;        private int start;        private int stop;        @Override        public void run() {            System.out.println(start + " - " + stop + "已完成排序!");            try {                barrier.await();            } catch (InterruptedException e) {                e.printStackTrace();            } catch (BrokenBarrierException e) {                e.printStackTrace();            }        }        public SortThread(CyclicBarrier barrier, int[] datas, int start, int stop) {            this.barrier = barrier;            this.datas = datas;            this.start = start;            this.stop = stop;        }    }    public static void main(String[] args) throws InterruptedException, BrokenBarrierException {        ExecutorService threadPool = Executors.newFixedThreadPool(16);        int count = 10;// 分10个线程排序        final CyclicBarrier barrier = new CyclicBarrier(count + 1/*这里是await的个数*/);        int[] datas = new int[1024];        int step = datas.length / count;        for (int i = 0; i < count; i++) {            int start = i * step;            int end = (i + 1) * step;            threadPool.submit(new SortThread(barrier, datas, start, end));        }        /**         * 每个线程都会在await方法处阻塞,当所有线程都已经在await状态时,当所有线程都已经准备就绪         * 发出通知唤醒所有线程同时开始执行         */        barrier.await();        //合并排序的数据        System.out.println("合并数据!");        threadPool.shutdown();    }}

CountDownLatch和CyclicBarrier的区别:
1. CountDownLatch是唤醒latch处于await的线程,CyclicBarrier是唤醒所有等待的线程
2. CyclicBarrier容易发生死锁,需要更大的线程池
3. CyclicBarrier可循环使用,CountDownLatch不可循环使用

Semaphore

        Semaphore semaphore = new Semaphore(count);        // 获取信号量        semaphore.acquire();        try {        } finally {            // 释放信号量            semaphore.release();        }

Exchanger

交换两线程的数据

import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.Exchanger;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Main {    public static class ExchangeThread implements Runnable {        private Exchanger<Integer> exchanger;        private int data;        private String name;        @Override        public void run() {            System.out.println("exchange before:" + name + " - " + data);            try {                data = exchanger.exchange(data);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("exchange after:" + name + " - " + data);        }        public ExchangeThread(Exchanger<Integer> exchanger, int data, String name) {            this.exchanger = exchanger;            this.data = data;            this.name = name;        }    }    public static void main(String[] args) throws InterruptedException, BrokenBarrierException {        ExecutorService threadPool = Executors.newFixedThreadPool(16);        final Exchanger<Integer> exchanger = new Exchanger<Integer>();        threadPool.submit(new ExchangeThread(exchanger, 1, "Thread_1"));        threadPool.submit(new ExchangeThread(exchanger, 2, "Thread_2"));        threadPool.shutdown();    }}

Future和FutureTask

  1. Callable位于java.util.concurrent包下,它也是一个接口,在它里面也只声明了一个方法,只不过这个方法叫做call(),一般情况下是配合ExecutorService来使用的。
  2. Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。Future提供了三种功能:判断任务是否完成、能够中断任务、能够获取任务执行结果。因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了FutureTask。
  3. FutureTask类实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现,可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
public interface RunnableFuture<V> extends Runnable, Future<V> {    void run();}
0 0
原创粉丝点击