描述
使用自定義線程池,模擬三個人上車
應用知識點
- 自定義線程池
- 線程工廠
- 線程池無法使用 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