0.9、自定義線程池並獲取線程池內運行結果

描述

使用自定義線程池,模擬三個人上車

應用知識點

  • 自定義線程池
  • 線程工廠
  • 線程池無法使用 join,使用 Future
  • 線程安全的 List: Collections.synchronizedList
  • CyclicBarrier
  • 線程池關閉
  • 線程池最佳線程數
在《Java Concurrency in Practice》一書中,給出了估算線程池大小的公式:
  Nthreads = Ncpu x Ucpu x (1 + W/C),其中
  Ncpu = CPU核心數
  Ucpu = CPU使用率,0~1
  W/C = 等待時間與計算時間的比率

代碼

import com.google.common.collect.Lists;
import org.apache.curator.shaded.com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.mortbay.util.ajax.JSON;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Title: 線程池測試
 * @Description: 線程池測試
 * @Author: wujie
 * @Version: v1.0
 * @Date:2020-06-10
 * @Updatedby:
 */
public class ThreadTest {
    private final static int CORE_POOL_SIZE = 10;
    private final static int MAX_I_MUM_POOL_SIZE = 10;
    private final static long KEEP_ALIVE_TIME = 0L;
    private final static int WORKQUEUE_SIZE = 1024;
    /**
     * 自定義線程名稱,方便的出錯的時候溯源
     */
    private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("center-pool-%d").build();
    private static ExecutorService threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_I_MUM_POOL_SIZE, KEEP_ALIVE_TIME,
            TimeUnit.MILLISECONDS, new LinkedBlockingDeque(WORKQUEUE_SIZE), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

    /**
     * 獲取線程池
     */
    public static ExecutorService getThreadPool() {
        return threadPool;
    }

    /**
     * 獲取線程池工廠
     */
    public static ThreadFactory getThreadFactory(){
        return namedThreadFactory;
    }

    /**
     * 執行任務
     * @param r
     */
    public static void newTask(Runnable r) {
        threadPool.execute(r);
    }

    /**
     * 關閉線程池(如有在執行任務則等待)
     */
    public static void destroyExecutorService(){
        System.out.println("關閉線程池");
        if(!threadPool.isShutdown()){
            threadPool.shutdown();
        }
    }

    /**
     * 立即關閉線程池
     */
    public static void destroyNowExecutorService(){
        System.out.println("立即關閉線程池");
        if(!threadPool.isShutdown()){
            threadPool.shutdownNow();
        }
    }

    /**
     * 線程池是否關閉
     * @return
     */
    public static boolean isExecutorServiceDownNow(){
        return threadPool.isShutdown();
    }



    public static void main(String[] args)  {

        List list = Collections.synchronizedList(Lists.newArrayList());

        Callable callable = new Callable() {
            @Override
            public Object call() throws Exception {
                System.out.println("駕駛員 "+Thread.currentThread().getName() + " 出發");
                return list;
            }
        };
        //將 callable 傳入到 FutureTask 構造函數
        FutureTask futureTask = new FutureTask(callable);
        CyclicBarrier c = new CyclicBarrier(1, namedThreadFactory.newThread((futureTask)));

        newTask(namedThreadFactory.newThread(new MyThread(c,list)));
        newTask(namedThreadFactory.newThread(new MyThread(c,list)));
        newTask(namedThreadFactory.newThread(new MyThread(c,list)));

        //獲取結果-這裏注意時間
        List listResult = null;
        try {
            listResult = (List) futureTask.get(2, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }finally {
            futureTask.cancel(true);
        }

        System.out.println(System.currentTimeMillis() + ":滿員嘍,都坐穩當了,本次列車出發咯");
        System.out.println("收到的門票:"+JSON.toString(listResult));
        destroyExecutorService();
        System.out.println("線程池是否關閉"+isExecutorServiceDownNow());

    }

    public static class MyThread extends Thread {
        private CyclicBarrier c;
        private List list;

        public MyThread(CyclicBarrier c,List list) {
            this.c = c;
            this.list = list;
        }

        public void run() {
            try {
                Thread.currentThread().sleep(120);
                list.add("門票"+System.currentTimeMillis()+"元");
                System.out.println("乘客 " + Thread.currentThread().getName() + " 坐好了");
                c.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            } 

        }
    }
}
運行結果
乘客 center-pool-2 坐好了
乘客 center-pool-4 坐好了
乘客 center-pool-6 坐好了
駕駛員 center-pool-2 出發
1591780796401:滿員嘍,都坐穩當了,本次列車出發咯
收到的門票:["門票1591780796400元","門票1591780796400元","門票1591780796400元"]
關閉線程池
線程池是否關閉true

Process finished with exit code 0

參考資料

[1]、https://www.cnblogs.com/xhq1024/p/12125290.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章