国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Timer與ScheduledThreadPoolExecutor

2019-11-14 12:49:10
字體:
供稿:網(wǎng)友

import java.text.SimpleDateFormat;  import java.util.Date;  import java.util.concurrent.ScheduledThreadPoolExecutor;  import java.util.concurrent.TimeUnit;    public class TestScheduledThreadPoolExecutor {        public static void main(String[] args) {                    String time = new SimpleDateFormat("HH:mm:ss").format(new Date());          System.out.PRintln("Start time : " + time);                    ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);  //創(chuàng)建5個(gè)執(zhí)行線程                    Runnable runnable = new Runnable() {                            @Override              public void run() {                  // TODO Auto-generated method stub                  String time = new SimpleDateFormat("HH:mm:ss").format(new Date());                  System.out.println("Now Time : "  + time);              }          };                    executor.scheduleWithFixedDelay(runnable, 2, 3, TimeUnit.SECONDS);                }        }  在實(shí)際應(yīng)用中,有時(shí)候我們需要?jiǎng)?chuàng)建一些個(gè)延遲的、并具有周期性的任務(wù),比如,我們希望當(dāng)我們的程序啟動(dòng)后每隔1小時(shí)就去做一次日志記錄。在JDK中提供了兩種方法去創(chuàng)建延遲周期性任務(wù)。

TimerTimer是java.util包下的一個(gè)類,在JDK1.3的時(shí)候被引入,Timer只是充當(dāng)了一個(gè)執(zhí)行者的角色,真正的任務(wù)邏輯是通過一個(gè)叫做TimerTask的抽象類完成的,TimerTask也是java.util包下面的類,它是一個(gè)實(shí)現(xiàn)了Runnable接口的抽象類,包含一個(gè)抽象方法run( )方法,需要我們自己去提供具體的業(yè)務(wù)實(shí)現(xiàn)。Timer類對(duì)象是通過其schedule方法執(zhí)行TimerTask對(duì)象中定義的業(yè)務(wù)邏輯,并且schedule方法擁有多個(gè)重載方法提供不同的延遲與周期性服務(wù)。下面是利用Timer去創(chuàng)建的一個(gè)延時(shí)周期性任務(wù)
import java.text.SimpleDateFormat;  import java.util.Date;  import java.util.Timer;  import java.util.TimerTask;    public class TestTimer {        public static void main(String[] args) {                    String time = new SimpleDateFormat("HH:mm:ss").format(new Date());          System.out.println("Start time : " + time);                    Timer timer = new Timer();          TimerTask task = new TimerTask() {                            @Override              public void run() {                  // TODO Auto-generated method stub                  String time = new SimpleDateFormat("HH:mm:ss").format(new Date());                  System.out.println("Now Time : "  + time);              }          }; //end task                    timer.schedule(task, 2000, 3000);                }        }  程序的輸出:Start time : 21:36:08  Now Time : 21:36:10  Now Time : 21:36:13  Now Time : 21:36:16  Now Time : 21:36:19  ScheduledThreadPoolExecutor在JDK1.5的時(shí)候在java.util.concurrent并發(fā)包下引入了ScheduledThreadPoolExecutor類,引入它的原因是因?yàn)門imer類創(chuàng)建的延遲周期性任務(wù)存在一些缺陷,ScheduledThreadPoolExecutor繼承了ThreadPoolExecutor,并且實(shí)現(xiàn)了ScheduledExecutorService接口,ScheduledThreadPoolExecutor也是通過schedule方法執(zhí)行Runnable任務(wù)的。我們用ScheduledThreadPoolExecutor來實(shí)現(xiàn)和上述Timer一樣的功能程序的輸出:Start time : 22:12:25  Now Time : 22:12:27  Now Time : 22:12:30  Now Time : 22:12:33  Now Time : 22:12:36  這樣看來Timer和ScheduledThreadPoolExecutor好像沒有聲明差別,但是ScheduledThreadPoolExecutor的引入正是由于Timer類存在的一些不足,并且在JDK1.5或更高版本中,幾乎沒有利用繼續(xù)使用Timer類,下面說明Timer存在的一些缺點(diǎn)。單線程Timer類是通過單線程來執(zhí)行所有的TimerTask任務(wù)的,如果一個(gè)任務(wù)的執(zhí)行過程非常耗時(shí),將會(huì)導(dǎo)致其他任務(wù)的時(shí)效性出現(xiàn)問題。而ScheduledThreadPoolExecutor是基于線程池的多線程執(zhí)行任務(wù),不會(huì)存在這樣的問題。這里我們通過讓Timer來執(zhí)行兩個(gè)TimerTask任務(wù)來說明,其中一個(gè)TimerTask的執(zhí)行過程是耗時(shí)的,加入需要2秒。
import java.text.SimpleDateFormat;  import java.util.Date;  import java.util.Timer;  import java.util.TimerTask;    public class SingleThreadTimer {        public static void main(String[] args) {                    String time = new SimpleDateFormat("HH:mm:ss").format(new Date());          System.out.println("Start time : " + time);                    Timer timer = new Timer();                    TimerTask task1 = new TimerTask() {                            @Override              public void run() {                  // TODO Auto-generated method stub                  String time = new SimpleDateFormat("HH:mm:ss").format(new Date());                  System.out.println("Task1 time : " + time);              }          };                    TimerTask task2 = new TimerTask() {                            @Override              public void run() {                  // TODO Auto-generated method stub                  try {                      Thread.sleep(2000);                  } catch (InterruptedException e) {                      // TODO Auto-generated catch block                      e.printStackTrace();                  }                  String time = new SimpleDateFormat("HH:mm:ss").format(new Date());                  System.out.println("task2 time : " + time);              }          };                    timer.schedule(task1, 2000, 1000);          timer.schedule(task2, 2000, 3000);      }        }  這里定義了兩個(gè)任務(wù),任務(wù)1,程序啟動(dòng)2秒后每隔1秒運(yùn)行一次,任務(wù)2,程序啟動(dòng)2秒后,每隔3秒運(yùn)行1次,然后讓Timer同時(shí)運(yùn)行這兩個(gè)任務(wù)程序的輸出如下:Start time : 22:22:37  Task1 time : 22:22:39  task2 time : 22:22:41  Task1 time : 22:22:41  Task1 time : 22:22:42  task2 time : 22:22:44  Task1 time : 22:22:44  Task1 time : 22:22:45  task2 time : 22:22:47  Task1 time : 22:22:47  Task1 time : 22:22:48  可以分析,無論是任務(wù)1還是任務(wù)2都沒有按照我們?cè)O(shè)定的預(yù)期進(jìn)行運(yùn)行,造成這個(gè)現(xiàn)象的原因就是Timer類是單線程的。Timer線程不捕獲異常Timer類中是不捕獲異常的,假如一個(gè)TimerTask中拋出未檢查異常(P.S:java中異常分為兩類:checked exception(檢查異常)和unchecked exception(未檢查異常),對(duì)于未檢查異常也叫RuntimeException(運(yùn)行時(shí)異常). ),Timer類將不會(huì)處理這個(gè)異常而產(chǎn)生無法預(yù)料的錯(cuò)誤。這樣一個(gè)任務(wù)拋出異常將會(huì)導(dǎo)致整個(gè)Timer中的任務(wù)都被取消,此時(shí)已安排但未執(zhí)行的TimerTask也永遠(yuǎn)不會(huì)執(zhí)行了,新的任務(wù)也不能被調(diào)度(所謂的“線程泄漏”現(xiàn)象)。下面就已常見的RuntimeException,ArrayIndexOutOfBoundsException數(shù)組越界異常,來演示這個(gè)缺點(diǎn):
import java.text.SimpleDateFormat;  import java.util.Date;  import java.util.Timer;  import java.util.TimerTask;    public class TestTimerTask {        public static void main(String[] args) {          System.out.println(new SimpleDateFormat("HH:mm:ss").format(new Date()));          Timer timer = new Timer();          TimerTask task1 = new TimerTask() {                        @Override              public void run() {                  System.out.println("1: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));              }          };                    TimerTask task2 = new TimerTask() {                            @Override              public void run() {                  int[] arr = {1,2,3,4,5};                  try {                      Thread.sleep(1000);                                        } catch (InterruptedException e) {                      e.printStackTrace();                  }                  int index = (int)(Math.random()*100);                  System.out.println(arr[index]);                                    System.out.println("2: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));              }          };                    timer.schedule(task1, 2000, 3000);          timer.schedule(task2, 2000, 1000);                }        }  程序會(huì)在運(yùn)行過程中拋出數(shù)組越界異常,并且整個(gè)程序都會(huì)被終止,原來完好的任務(wù)1也被終止了。基于絕對(duì)時(shí)間Timer類的調(diào)度是基于絕對(duì)的時(shí)間的,而不是相對(duì)的時(shí)間,因此Timer類對(duì)系統(tǒng)時(shí)鐘的變化是敏感的,舉個(gè)例子,加入你希望任務(wù)1每個(gè)10秒執(zhí)行一次,某個(gè)時(shí)刻,你將系統(tǒng)時(shí)間提前了6秒,那么任務(wù)1就會(huì)在4秒后執(zhí)行,而不是10秒后。在ScheduledThreadPoolExecutor,任務(wù)的調(diào)度是基于相對(duì)時(shí)間的,原因是它在任務(wù)的內(nèi)部存儲(chǔ)了該任務(wù)距離下次調(diào)度還需要的時(shí)間(使用的是基于System#nanoTime實(shí)現(xiàn)的相對(duì)時(shí)間,不會(huì)因?yàn)橄到y(tǒng)時(shí)間改變而改變,如距離下次執(zhí)行還有10秒,不會(huì)因?yàn)閷⑾到y(tǒng)時(shí)間調(diào)前6秒而變成4秒后執(zhí)行)。基于以上3個(gè)弊端,在JDK1.5或以上版本中,我們幾乎沒有理由繼續(xù)使用Timer類,ScheduledThreadPoolExecutor可以很好的去替代Timer類來完成延遲周期性任務(wù)。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 昌图县| 德安县| 明光市| 社会| 桃园市| 凭祥市| 新蔡县| 昌宁县| 东源县| 南投县| 施甸县| 福泉市| 牟定县| 始兴县| 龙海市| 安图县| 南城县| 德江县| 漳平市| 云林县| 呼玛县| 红安县| 屯门区| 大同市| 荆州市| 洞口县| 邓州市| 揭西县| 东兴市| 巴南区| 玉屏| 冕宁县| 宁乡县| 灵石县| 房产| 获嘉县| 太仆寺旗| 泽库县| 三江| 静海县| 汾西县|