Java并发编程:同步工具类

78 阅读2分钟

src=http___i0.hdslb.com_bfs_article_807aa46619617caf3a3ea976300b575abae0676c.png&refer=http___i0.hdslb.webp 本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

       上文(《Java并发编程:发布与逸出》)给大家介绍了多线程中发布与逸出的方式以及解决方法,而本片文章将给大家介绍的是几个常用的同步工具类,并通过几个实例,让大家可以进行快速入门。

闭锁(CountDownLatch)

  • 闭锁就相当于一个大门,只有等所有线程都到达之后,门才会开。例如:我约了其它三个人一起打麻将,之后等我们四个人都到了之后,才能开始打麻将。
private static void testCountDownLatch() {
        final CountDownLatch start = new CountDownLatch(1);
        final CountDownLatch end = new CountDownLatch(3);
        new Thread() {
            @Override
            public void run() {
                try {
                    start.await();
                    System.out.println("CountDownLatch Thread1 working...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    end.countDown();
                }
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                try {
                    start.await();
                    System.out.println("CountDownLatch Thread2 working...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    end.countDown();
                }
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                try {
                    start.await();
                    System.out.println("CountDownLatch Thread3 working...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    end.countDown();
                }
            }
        }.start();

        System.out.println("CountDownLatch Threads start...");
        start.countDown();
        try {
            end.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("CountDownLatch Threads finish...");
    }

FutureTask

  • FutureTask的get方法,如果还没运行结束时,会一直阻塞,直到有结果。
private static void testFutureTask() {
        FutureTask<String> future = new FutureTask<String>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "FutureTask test...";
            }
        });

        try {
            future.run();
            System.out.println(future.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Semaphore信号量

  • 信号量在使用时,要先获取信号量,如果获取到了,才能继续执行,否则将一直阻塞,直到获取到信号量。
private static void testSemaphore() {
        Semaphore semaphore = new Semaphore(1);
        try {
            semaphore.acquire();
            System.out.println("Semaphore test...");
            semaphore.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

栅栏

  • 栅栏跟闭锁有点类似。不过闭锁是等待外部事件的触发,而栅栏是所有线程相互等待,直到某个点,栅栏才打开。
public class TestBarrier {
    private Board mainBoard;
    private CyclicBarrier barrier;
    private int nums = 5;
    private int dealCount = 0;

    public TestBarrier(final int cpuNum) {
        mainBoard = new Board();
        barrier = new CyclicBarrier(cpuNum, new Runnable() {
            @Override
            public void run() {
                dealCount += cpuNum;
                if (dealCount != nums) {
                    System.out.println("数据尚未处理完...");
                } else {
                    System.out.println("Result=" + mainBoard.getResult());
                }
            }
        });
        for (int i = 0; i < cpuNum; i++) {
            new Thread(new Worker(mainBoard, i + 1)).start();
        }
    }

    /**
     * 具体算法
     * 
     * @author HuangXiquan
     *
     */
    private class Worker implements Runnable {
        private Board board;
        private int number;// 要计算的数值

        public Worker(Board board, int number) {
            this.board = board;
            this.number = number;
        }

        @Override
        public void run() {
            System.out.println("Worker compute number=" + number);
            board.setResult(number - 1, number * number);
            try {
                barrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

    private class Board {
        private int[] result = new int[nums];

        public void setResult(int index, int value) {
            result[index] = value;
        }

        public int getResult() {
            int value = 0;
            for (int i = 0; i < result.length; i++) {
                value += result[i];
            }

            return value;
        }
    }

    public static void main(String[] args) {
        int cpuNum = Runtime.getRuntime().availableProcessors();
        System.out.println("cpuNum=" + cpuNum);
        new TestBarrier(cpuNum);
    }

}

后言

       既然看到这里了,感觉有所收获的朋友,不妨来个大大的点赞吧~~~