Second, concurrent Tools

Fork/Join

Fork / Join framework Java 7 to provide a framework for parallel execution of a task is a big task to task is divided into several small, to obtain a large frame final summary results of the task results after each small task. Fork / Join framework to accomplish two things:

  1. Task division: First Fork / Join framework needs to split large tasks into small enough sub-tasks, if the task is relatively large, then the child should continue dividing the sub-tasks
  2. Mission and merging the results: sub-tasks are split into double-ended queue, then start several threads are acquired from the double-ended task execution queue. The results of executing the subtasks are placed in another queue, start a thread fetch data from the queue, and then merge the data.

Fork / Join framework needed to achieve these functions through two classes
ForkJoinTask: ForkJoin create a task, which can be inherited ForkJoinTask two subclasses

  • RecursiveAction: did not return for the results of the task
  • RecursiveTask: There used to return the results of the task

ForkJoinPool: a ForkJoin task needs to be performed by ForkJoinPool

A simple example of using RecursiveTask: Calculated 1000000000 and 2 using Fork / Join framework

/**
 * @CalssName RecursiveTaskDemo
 * @Description 使用Fork/Join框架计算10亿个2的和
 * @since JDK 1.8
 */
public class RecursiveTaskDemo {

    private static final int ARRAY_SIZE = 10_0000_0000;

    public static int[] findArr() {
        int[] array = new int[ARRAY_SIZE];
        for (int i = 0; i < ARRAY_SIZE; i++) {
            array[i] = 2;
        }
        return array;
    }

    //有返回值的task
    public static class SumTask extends RecursiveTask<Integer> {
        private static final int THRESHOLD = ARRAY_SIZE / 10;//阈值,拆分的最小单位
        private int[] arr;
        private int left;
        private int right;

        public SumTask(int[] arr, int left, int right) {
            this.arr = arr;
            this.left = left;
            this.right = right;
        }

        @Override
        protected Integer compute() {
            if ((right - left) > THRESHOLD) {
                //大于拆分的最小单位,继续拆分
                int middle = (right + left) / 2;
                SumTask leftTask = new SumTask(this.arr, left, middle);
                SumTask rightTask = new SumTask(this.arr, middle + 1, right);

                //拆分
                leftTask.fork();
                rightTask.fork();
                //或者
//                invokeAll(leftTask, rightTask);

                //合并
                return leftTask.join() + rightTask.join();
            } else {
                int count = 0;
                for (int i = left; i <= right; i++) {
                    count += arr[i];
                }
                return count;
            }
        }
    }

    public static void main(String[] args) {

        int[] arr = findArr();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        SumTask sumTask = new SumTask(arr, 0, arr.length - 1);
        long start = System.currentTimeMillis();
        forkJoinPool.invoke(sumTask);
        System.out.println("sum:" + sumTask.join() + " 用时:" + (System.currentTimeMillis() - start) + "毫秒");
        //sum:2000000000 用时:259毫秒

//        start = System.currentTimeMillis();
//        int count = 0;
//        for (int i = 0; i < ARRAY_SIZE; i++) {
//            count += arr[i];
//        }
//        System.out.println("sum:" + count + " 用时:" + (System.currentTimeMillis() - start) + "毫秒");
        //sum:2000000000 用时:445毫秒
    }
}

RecursiveAction Example: searching for files

/**
 * @CalssName RecursiveActionDemo
 * @Description 搜索文件
 * @since JDK 1.8
 */
public class RecursiveActionDemo {

    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool();
        SearchFileTask searchFileTask = new SearchFileTask(new File("D:/"), "spring-cloud");
        pool.execute(searchFileTask);
        searchFileTask.join();
    }
}

class SearchFileTask extends RecursiveAction {
    private File file;
    private String searchKey;

    public SearchFileTask(File file, String searchKey) {
        this.file = file;
        this.searchKey = searchKey;
    }

    @Override
    protected void compute() {
        List<SearchFileTask> searchFileTasks = new ArrayList<>();

        File[] files = file.listFiles();
        if (files != null) {
            for (File file1 : files) {
                if (file1.isDirectory()) {
                    searchFileTasks.add(new SearchFileTask(file1, searchKey));
                } else {
                    //文件
                    if (file1.getAbsolutePath().indexOf(searchKey) != -1) {
                        System.out.println("文件:" + file1.getAbsolutePath());
                    }
                }
            }
            if (!searchFileTasks.isEmpty()) {
                for (SearchFileTask task : invokeAll(searchFileTasks)) {
                    task.join();
                }
            }
        }
    }
}

Divide and conquer: Divide and conquer is a big task will be split into a number of layers of small tasks, it can not be split up, split according to the division of tasks defined threshold scale.
fork / join big task by the fork split into smaller tasks, in the summary of the results of small tasks join

CountDownLatch

CountDownLatch role is to wait after the implementation of a set of threads waiting in the execution threads

Examples

/**
 * @CalssName CountDownLatchDemo
 * @Description CountDownLatch示例
 * @since JDK 1.8
 */
public class CountDownLatchDemo {
    //计数5
    static CountDownLatch latch = new CountDownLatch(5);

    static class sumRunnable implements Runnable {
        @Override
        public void run() {
            latch.countDown();//每执行一次,计数减1
            System.out.println("求和计算。。。");
        }
    }

    static class subRunnable implements Runnable {
        @Override
        public void run() {
            latch.countDown();
            System.out.println("减法计算。。。");
        }
    }

    public static void main(String[] args) {
        try {
            new Thread(new sumRunnable()).start();
            new Thread(new sumRunnable()).start();
            new Thread(new subRunnable()).start();
            new Thread(new subRunnable()).start();
            new Thread(new sumRunnable()).start();

            latch.await();//直到调用了countDown()方法的线程执行完,计数减到0为止,才会继续执行main方法
            System.out.println("执行main方法。。。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

CyclicBarrier

Agreed to continue to wait while other threads are running together to the waiting position at a specified position threads running

Examples

/**
 * @CalssName CyclicBarrierDemo
 * @Description CyclicBarrier示例
 * @since JDK 1.8
 */
public class CyclicBarrierDemo {

    static CyclicBarrier barrier = new CyclicBarrier(3);

    public static void main(String[] args) {
        new Thread(new InitRunnable()).start();
        new Thread(new InitRunnable()).start();
        new Thread(new InitRunnable()).start();
    }

    //初始化线程
    static class InitRunnable implements Runnable {
        @Override
        public void run() {
            try {
                System.out.println("初始化前....");
                Random random = new Random();
                if (random.nextBoolean()) {
                    Thread.sleep(3000);
                }
                barrier.await();
                System.out.println("初始化后....");
            } catch (BrokenBarrierException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

operation result:

初始化前....
初始化前....
初始化前....
初始化后....
初始化后....
初始化后....

Summary operating data collection

/**
 * @CalssName CyclicBarrierDemo
 * @Description CyclicBarrier示例
 * @since JDK 1.8
 */
public class CyclicBarrierDemo {

    static CyclicBarrier barrier = new CyclicBarrier(3, new CollectRunnable());
    static ConcurrentHashMap<Long, String> collocatMap = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        new Thread(new InitRunnable(), "线程1").start();
        new Thread(new InitRunnable()).start();
        new Thread(new InitRunnable()).start();
    }

    //收集数据汇总
    static class CollectRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("在运行线程:" + collocatMap);
        }
    }

    //初始化线程
    static class InitRunnable implements Runnable {
        @Override
        public void run() {
            long threadId = Thread.currentThread().getId();
            collocatMap.put(threadId, Thread.currentThread().getName());
            try {
                System.out.println("初始化前....");
                Random random = new Random();
                if (random.nextBoolean()) {
                    Thread.sleep(3000);
                }
                barrier.await();
                System.out.println("初始化后....");
            } catch (BrokenBarrierException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Semaphore Semaphore

Control access to a resource at the same time the number of threads used for flow control

Connection Pooling Example

/**
 * @CalssName DBPool
 * @Description 数据库链接池工具
 * @since JDK 1.8
 */
public class DBPool {

    private static LinkedList<Connection> pool = new LinkedList<>();
    private static String url = "jdbc:mysql://192.168.86.101:3306/mysql";
    private static String username = "root";
    private static String password = "my-pwd";

    private final Semaphore useful;

    /**
     * @return java.sql.Connection
     * @Title getConnection
     * @Description 从链接池中获取链接,如果没有链接了在指定有效时间内获取链接,不然返回null
     * @Throws InterruptedException
     */
    public Connection getConnection() throws InterruptedException {
        useful.acquire();//获取,减1
        Connection connection;
        synchronized (pool) {
            connection = pool.removeFirst();
            System.out.println("连接池中还有"+useful.availablePermits()+"个链接,阻塞线程为"+useful.getQueueLength()+"个");
        }
        return connection;
    }

    /**
     * @Title 回收链接
     * @Param [connection]
     * @return void
     */
    public void recyclingConnection(Connection connection) {
        useful.release();//释放,加1,acquire()方法往下执行
        if (connection != null) {
            synchronized (pool) {
                pool.addLast(connection);
            }
        }
    }

    /**
     * @CalssName DBPool
     * @Description 初始化链接池
     * @since JDK 1.8
     */
    public DBPool(int initSize) {
        this.useful = new Semaphore(initSize);
        if (initSize > 0) {
            try {
                Class.forName("com.mysql.jdbc.Driver");
                for (int i = 0; i < initSize; i++) {
                    Connection connection = DriverManager.getConnection(url, username, password);
                    pool.add(connection);
                }
            } catch (ClassNotFoundException | SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

test

/**
 * @CalssName App
 * @Description Semaphore信号量测试
 * @since JDK 1.8
 */
public class App {

    static DBPool dbPool = new DBPool(10);
    private static class BusiThread implements Runnable {
        @Override
        public void run() {
            Connection conn = null;
            Random random = new Random();
            try {
                conn = dbPool.getConnection();
                //模拟业务处理
                Thread.sleep(10 * random.nextInt(500));
                dbPool.recyclingConnection(conn);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        DBPool pool = new DBPool(10);
        for (int i = 0; i < 50; i++) {
            new Thread(new BusiThread()).start();
        }
    }
}

Guess you like

Origin www.cnblogs.com/yhongyin/p/11117875.html