利用线程池为线程创建一个守护线程
生活随笔
收集整理的這篇文章主要介紹了
利用线程池为线程创建一个守护线程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
主線程:
public class MainThread implements Callable {SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS" );@Overridepublic Integer call() throws Exception {for (int i = 0; i < 10; i++) {Thread.sleep(200*i);Date now= new Date();System.out.println(Thread.currentThread() +":"+sdf.format(now));}return 0;} }守護線程:
public class DeamonThread implements Callable<String> {private Future<Integer> mainThread;SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss" );public DeamonThread() {}public DeamonThread(Future<Integer> mainThread) {this.mainThread = mainThread;}@Overridepublic String call() throws Exception {try{//如果主線程已執行完,則不在這里浪費時間if(!mainThread.isDone() || !mainThread.isCancelled()){//如果主線程執行超過2s,執行守護線程finally語句內代碼Thread.sleep(2000);System.out.println("守護線程等待了2s");}}catch (InterruptedException e){}finally {if(!mainThread.isDone() || !mainThread.isCancelled()){mainThread.cancel(true);}System.out.println("主線程執行超時,主線程結束");}return "";} }測試:
public class ThreadPoolDemo {public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor = null;try {MainThread mainThread = new MainThread();threadPoolExecutor = new ThreadPoolExecutor(2, 2, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1));Future<Integer> mainResult = threadPoolExecutor.submit(mainThread);DeamonThread deamonThread1 = new DeamonThread(mainResult);threadPoolExecutor.submit(deamonThread1);System.out.println("*****"+mainResult.get()+"*****");}catch (Exception e){}finally {if(threadPoolExecutor!=null){threadPoolExecutor.shutdown();}}} }主線程執行超過2s任務被取消:
細心的話可以發現:
這句代碼沒執行,查看原因
可以看出是調用mainResult.get()方法時發生CancellationException異常(由于任務執行中斷,被取消)
另外,線程池中,不同任務間是競爭執行的,不會按代碼順序去一步一步執行,所以守護線程可以在主線程執行過程中得到主線程返回的Future mainResult對象。
除了多線程任務執行無序,事實上當前main方法線程和線程池中的多線程任務也會并發執行,修改部分代碼:
可以看出,先把main方法中for循環代碼執行了(耗時較短,瞬間執行完畢,如果與線程池任務耗時相當,則可看見交替執行效果),而System.out.println("*****"+mainResult.get()+"*****");后邊的for語句因為get()方法拋異常,未被執行。而get()方法本身是個阻塞方法,是在線程池任務結束后才執行的,以便獲取實際返回值(畢竟線程任務如果是查詢任務,我們需要其實際返回值)。
總結
以上是生活随笔為你收集整理的利用线程池为线程创建一个守护线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: @EnableCaching与@Cach
- 下一篇: class.getResourceAsS