package com.test;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Date: 2017/12/14</p>
 *
 * @author XN
 * @version 1.0
 */
//@ContextConfiguration(locations = {"classpath*:application/applicationContext*.xml"})
//@RunWith(SpringJUnit4ClassRunner.class)
public class ExecutorPoolTest {

    @Test
    public void test() {
        ExecutorService pool = Executors.newFixedThreadPool(5);
        try {
            // 创建容量为NUMBER的线程池。
            ArrayList<Future<Integer>> futures = new ArrayList<Future<Integer>>();
            ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService(pool);
            final Random random = new Random();
            for (int i = 0; i < 2; i++) {
                GetCustomers t = new GetCustomers(i, random.nextInt(100));
                System.out.println("init:" + t.id + " -> time." + t.sleepTime);
                Future<Integer> f = completionService.submit(t);
                futures.add(f);
            }

            /**
             * 而CompletionService的实现是维护一个保存Future对象的BlockingQueue。
             * 只有当这个Future对象状态是结束的时候，才会加入到这个Queue中，
             * take()方法其实就是Producer-Consumer中的Consumer。它会从Queue中取出Future对象，
             * 如果Queue是空的，就会阻塞在那里，直到有完成的Future对象加入到Queue中。
             */

            int doenTask = 0;
            while (doenTask < futures.size()) {
                System.out.println("获取结果中... :doenTask" + doenTask + ":size" + futures.size());
                Integer res = completionService.take().get();
                System.out.println("得到结果." + res);
                doenTask++;
            }

            //            int completionTask = 0;
            //            while(completionTask < futures.size()) {
            //                System.out.println("获取结果中... :doenTask"+completionTask+":size"+futures.size());
            //                //如果完成队列中没有数据, 则阻塞; 否则返回队列中的数据
            //                Future<Integer> resultHolder = completionService.take();
            //                System.out.println("result: " + resultHolder.get());
            //                completionTask++;
            //            }

            //            boolean done = false;
            //            for (Future<Integer> fs : futures) {
            //                System.out.println("runing... get : ");
            //                while (!fs.isDone()) {
            //                    System.out.println("runing... done : " + fs.get());
            //                    Thread.sleep(10);
            //                }
            //                done = true;
            //                doenTask++;
            //                System.out.println("done>>" + fs.get());
            //            }

            // 关闭线程池。
            pool.shutdown();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            pool.shutdown();
        }
    }

    private class GetCustomers implements Callable<Integer> {
        private AtomicInteger atomicInteger = new AtomicInteger(0);
        private int id;
        private int sleepTime;

        public GetCustomers(int id, int sleepTime) {
            this.id = id;
            this.sleepTime = sleepTime;
        }

        @Override
        public Integer call() throws InterruptedException {
            System.out.println("线程:" + id + " ,sleep" + sleepTime + "-> 运行...");

            for (int i = 0; i <= 100; i++) {
                //Do something what U want
                atomicInteger.set(atomicInteger.get() + 1);
                Thread.sleep(sleepTime);
            }

            System.out.println("线程:" + id + " -> 结束.");
            return atomicInteger.get();
        }
    }

}
