程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 解析Java中的准時器及應用准時器制造彈彈球游戲的示例

解析Java中的准時器及應用准時器制造彈彈球游戲的示例

編輯:關於JAVA

解析Java中的准時器及應用准時器制造彈彈球游戲的示例。本站提示廣大學習愛好者:(解析Java中的准時器及應用准時器制造彈彈球游戲的示例)文章只能為提供參考,不一定能成為您想要的結果。以下是解析Java中的准時器及應用准時器制造彈彈球游戲的示例正文


  在我們編程進程中假如須要履行一些簡略的准時義務,不必做龐雜的掌握,我們可以斟酌應用JDK中的Timer准時義務來完成。上面LZ就其道理、實例和Timer缺點三個方面來解析java Timer准時器。

1、簡介
      在java中一個完全准時義務須要由Timer、TimerTask兩個類來合營完成。 API中是如許界說他們的,Timer:一種對象,線程用其支配今後在後台線程中履行的義務。可支配義務履行一次,或許按期反復履行。由TimerTask:Timer 支配為一次履行或反復履行的義務。我們可以如許懂得Timer是一種准時器對象,用來在一個後台線程籌劃履行指定義務,而TimerTask一個籠統類,它的子類代表一個可以被Timer籌劃的義務。
Timer類
      在對象類Timer中,供給了四個結構辦法,每一個結構辦法都啟動了計時器線程,同時Timer類可以包管多個線程可以同享單個Timer對象而無需停止內部同步,所以Timer類是線程平安的。然則因為每個Timer對象對應的是單個後台線程,用於次序履行一切的計時器義務,普通情形下我們的線程義務履行所消費的時光應當異常短,然則因為特別情形招致某個准時器義務履行的時光太長,那末他就會“獨有”計時器的義務履行線程,厥後的一切線程都必需期待它履行完,這就會延遲後續義務的履行,使這些義務聚積在一路,詳細情形我們前面剖析。
      當法式初始化完成Timer後,准時義務就會依照我們設定的時光去履行,Timer供給了schedule辦法,該辦法有多中重載方法來順應分歧的情形,以下:
      schedule(TimerTask task, Date time):支配在指定的時光履行指定的義務。
      schedule(TimerTask task, Date firstTime, long period) :支配指定的義務在指定的時光開端停止反復的固定延遲履行。
      schedule(TimerTask task, long delay) :支配在指定延遲後履行指定的義務。
      schedule(TimerTask task, long delay, long period) :支配指定的義務從指定的延遲後開端停止反復的固定延遲履行。
      同時也重載了scheduleAtFixedRate辦法,scheduleAtFixedRate辦法與schedule雷同,只不外他們的著重點分歧,差別前面剖析。
      scheduleAtFixedRate(TimerTask task, Date firstTime, long period):支配指定的義務在指定的時光開端停止反復的固定速度履行。
      scheduleAtFixedRate(TimerTask task, long delay, long period):支配指定的義務在指定的延遲後開端停止反復的固定速度履行。
TimerTask
      TimerTask類是一個籠統類,由Timer 支配為一次履行或反復履行的義務。它有一個籠統辦法run()辦法,該辦法用於履行響應計時器義務要履行的操作。是以每個詳細的義務類都必需繼續TimerTask,然後重寫run()辦法。
      別的它還有兩個非籠統的辦法:
      boolean cancel():撤消此計時器義務。
      long scheduledExecutionTime():前往此義務比來現實履行的支配履行時光。

2、實例
2.1、指定延遲時光履行准時義務

public class TimerTest01 { 
 Timer timer; 
 public TimerTest01(int time){ 
  timer = new Timer(); 
  timer.schedule(new TimerTaskTest01(), time * 1000); 
 } 
  
 public static void main(String[] args) { 
  System.out.println("timer begin...."); 
  new TimerTest01(3); 
 } 
} 
 
public class TimerTaskTest01 extends TimerTask{ 
 
 public void run() { 
  System.out.println("Time's up!!!!"); 
 } 
} 

運轉成果:

起首打印:

timer begin.... 

 
3秒後打印:

Time's up!!!! 

2.2、在指准時間履行准時義務

public class TimerTest02 { 
 Timer timer; 
  
 public TimerTest02(){ 
  Date time = getTime(); 
  System.out.println("指准時間time=" + time); 
  timer = new Timer(); 
  timer.schedule(new TimerTaskTest02(), time); 
 } 
  
 public Date getTime(){ 
  Calendar calendar = Calendar.getInstance(); 
  calendar.set(Calendar.HOUR_OF_DAY, 11); 
  calendar.set(Calendar.MINUTE, 39); 
  calendar.set(Calendar.SECOND, 00); 
  Date time = calendar.getTime(); 
   
  return time; 
 } 
  
 public static void main(String[] args) { 
  new TimerTest02(); 
 } 
} 
 
public class TimerTaskTest02 extends TimerTask{ 
 
 @Override 
 public void run() { 
  System.out.println("指准時間履行線程義務..."); 
 } 
} 

其時間達到11:39:00時就會履行該線程義務,固然年夜於該時光也會履行!!履行成果為:

指准時間time=Tue Jun 10 11:39:00 CST 2014 
指准時間履行線程義務... 

2.3、在延遲指准時間後以指定的距離時光輪回履行准時義務

public class TimerTest03 { 
 Timer timer; 
  
 public TimerTest03(){ 
  timer = new Timer(); 
  timer.schedule(new TimerTaskTest03(), 1000, 2000); 
 } 
  
 public static void main(String[] args) { 
  new TimerTest03(); 
 } 
} 
 
public class TimerTaskTest03 extends TimerTask{ 
 
 @Override 
 public void run() { 
  Date date = new Date(this.scheduledExecutionTime()); 
  System.out.println("本次履行該線程的時光為:" + date); 
 } 
} 

運轉成果:

本次履行該線程的時光為:Tue Jun 10 21:19:47 CST 2014 
本次履行該線程的時光為:Tue Jun 10 21:19:49 CST 2014 
本次履行該線程的時光為:Tue Jun 10 21:19:51 CST 2014 
本次履行該線程的時光為:Tue Jun 10 21:19:53 CST 2014 
本次履行該線程的時光為:Tue Jun 10 21:19:55 CST 2014 
本次履行該線程的時光為:Tue Jun 10 21:19:57 CST 2014 
................. 

      關於這個線程義務,假如我們不將該義務停滯,他會一向運轉下去。
      關於下面三個實例,LZ只是簡略的演示了一下,同時也沒有講授scheduleAtFixedRate辦法的例子,其實該辦法與schedule辦法一樣!
2.4、剖析schedule和scheduleAtFixedRate
(1)schedule(TimerTask task, Date time)、schedule(TimerTask task, long delay)
      關於這兩個辦法而言,假如指定的籌劃履行時光scheduledExecutionTime<= systemCurrentTime,則task會被立刻履行。scheduledExecutionTime不會由於某一個task的過度履行而轉變。
(2)schedule(TimerTask task, Date firstTime, long period)、schedule(TimerTask task, long delay, long period)
      這兩個辦法與下面兩個就有點兒分歧的,後面提過Timer的計時器義務會由於前一個義務履行時光較長而延時。在這兩個辦法中,每次履行的task的籌劃時光會跟著前一個task的現實時光而產生轉變,也就是scheduledExecutionTime(n+1)=realExecutionTime(n)+periodTime。也就是說假如第n個task因為某種情形招致此次的履行時光進程,最初招致systemCurrentTime>= scheduledExecutionTime(n+1),這是第n+1個task其實不會由於到時了而履行,他會期待第n個task履行完以後再履行,那末如許必將會招致n+2個的履行完成scheduledExecutionTime放生轉變即scheduledExecutionTime(n+2) = realExecutionTime(n+1)+periodTime。所以這兩個辦法加倍重視保留距離時光的穩固。
(3)scheduleAtFixedRate(TimerTask task, Date firstTime, long period)、scheduleAtFixedRate(TimerTask task, long delay, long period)
      在後面也提過scheduleAtFixedRate與schedule辦法的著重點分歧,schedule辦法著重保留距離時光的穩固,而scheduleAtFixedRate辦法加倍著重於堅持履行頻率的穩固。為何這麼說,緣由以下。在schedule辦法中會由於前一個義務的延遲而招致厥後面的准時義務延時,而scheduleAtFixedRate辦法則不會,假如第n個task履行時光太長招致systemCurrentTime>= scheduledExecutionTime(n+1),則不會做任多麼待他會立刻履行第n+1個task,所以scheduleAtFixedRate辦法履行時光的盤算辦法分歧於schedule,而是scheduledExecutionTime(n)=firstExecuteTime +n*periodTime,該盤算辦法永久堅持不變。所以scheduleAtFixedRate加倍著重於堅持履行頻率的穩固。

3、Timer的缺點
3.1、Timer的缺點
      Timer計時器可以准時(指准時間履行義務)、延遲(延遲5秒履行義務)、周期性地履行義務(每隔個1秒履行義務),然則,Timer存在一些缺點。起首Timer對換度的支撐是基於相對時光的,而不是絕對時光,所以它對體系時光的轉變異常敏感。其次Timer線程是不會捕捉異常的,假如TimerTask拋出的了未檢討異常則會招致Timer線程終止,同時Timer也不會從新恢單線程的履行,他會毛病的以為全部Timer線程都邑撤消。同時,曾經被支配單還沒有履行的TimerTask也不會再履行了,新的義務也不克不及被調劑。故假如TimerTask拋出未檢討的異常,Timer將會發生沒法預感的行動。
(1)Timer治理時光延遲缺點
      後面Timer在履行准時義務時只會創立一個線程義務,假如存在多個線程,若個中某個線程由於某種緣由而招致線程義務履行時光太長,跨越了兩個義務的距離時光,會產生一些缺點:

public class TimerTest04 { 
 private Timer timer; 
 public long start;  
  
 public TimerTest04(){ 
  this.timer = new Timer(); 
  start = System.currentTimeMillis(); 
 } 
  
 public void timerOne(){ 
  timer.schedule(new TimerTask() { 
   public void run() { 
    System.out.println("timerOne invoked ,the time:" + (System.currentTimeMillis() - start)); 
    try { 
     Thread.sleep(4000); //線程休眠3000 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
   } 
  }, 1000); 
 } 
  
 public void timerTwo(){ 
  timer.schedule(new TimerTask() { 
   public void run() { 
    System.out.println("timerOne invoked ,the time:" + (System.currentTimeMillis() - start)); 
   } 
  }, 3000); 
 } 
  
 public static void main(String[] args) throws Exception { 
  TimerTest04 test = new TimerTest04(); 
   
  test.timerOne(); 
  test.timerTwo(); 
 } 
} 

      依照我們正常思緒,timerTwo應當是在3s後履行,其成果應當是:

timerOne invoked ,the time:1001 
timerOne invoked ,the time:3001 

      然則適得其反,timerOne因為sleep(4000),休眠了4S,同時Timer外部是一個線程,招致timeOne所需的時光跨越了距離時光,成果:

timerOne invoked ,the time:1000 
timerOne invoked ,the time:5000 

 
(2)Timer拋出異常缺點
假如TimerTask拋出RuntimeException,Timer會終止一切義務的運轉。以下:

public class TimerTest04 { 
 private Timer timer; 
  
 public TimerTest04(){ 
  this.timer = new Timer(); 
 } 
  
 public void timerOne(){ 
  timer.schedule(new TimerTask() { 
   public void run() { 
    throw new RuntimeException(); 
   } 
  }, 1000); 
 } 
  
 public void timerTwo(){ 
  timer.schedule(new TimerTask() { 
    
   public void run() { 
    System.out.println("我會不會履行呢??"); 
   } 
  }, 1000); 
 } 
  
 public static void main(String[] args) { 
  TimerTest04 test = new TimerTest04(); 
  test.timerOne(); 
  test.timerTwo(); 
 } 
} 

運轉成果:timerOne拋出異常,招致timerTwo義務終止。

Exception in thread "Timer-0" java.lang.RuntimeException 
 at com.chenssy.timer.TimerTest04$1.run(TimerTest04.java:25) 
 at java.util.TimerThread.mainLoop(Timer.java:555) 
 at java.util.TimerThread.run(Timer.java:505) 

關於Timer的缺點,我們可以斟酌 ScheduledThreadPoolExecutor 來替換。Timer是基於相對時光的,對體系時光比擬敏感,而ScheduledThreadPoolExecutor 則是基於絕對時光;Timer是外部是單一線程,而ScheduledThreadPoolExecutor外部是個線程池,所以可以支撐多個義務並發履行。
3.2、用ScheduledExecutorService替換Timer
(1)處理成績一:

public class ScheduledExecutorTest { 
 private ScheduledExecutorService scheduExec; 
  
 public long start; 
  
 ScheduledExecutorTest(){ 
  this.scheduExec = Executors.newScheduledThreadPool(2); 
  this.start = System.currentTimeMillis(); 
 } 
  
 public void timerOne(){ 
  scheduExec.schedule(new Runnable() { 
   public void run() { 
    System.out.println("timerOne,the time:" + (System.currentTimeMillis() - start)); 
    try { 
     Thread.sleep(4000); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
   } 
  },1000,TimeUnit.MILLISECONDS); 
 } 
  
 public void timerTwo(){ 
  scheduExec.schedule(new Runnable() { 
   public void run() { 
    System.out.println("timerTwo,the time:" + (System.currentTimeMillis() - start)); 
   } 
  },2000,TimeUnit.MILLISECONDS); 
 } 
  
 public static void main(String[] args) { 
  ScheduledExecutorTest test = new ScheduledExecutorTest(); 
  test.timerOne(); 
  test.timerTwo(); 
 } 
} 

運轉成果:

timerOne,the time:1003 
timerTwo,the time:2005 

(2)處理成績二

public class ScheduledExecutorTest { 
 private ScheduledExecutorService scheduExec; 
  
 public long start; 
  
 ScheduledExecutorTest(){ 
  this.scheduExec = Executors.newScheduledThreadPool(2); 
  this.start = System.currentTimeMillis(); 
 } 
  
 public void timerOne(){ 
  scheduExec.schedule(new Runnable() { 
   public void run() { 
    throw new RuntimeException(); 
   } 
  },1000,TimeUnit.MILLISECONDS); 
 } 
  
 public void timerTwo(){ 
  scheduExec.scheduleAtFixedRate(new Runnable() { 
   public void run() { 
    System.out.println("timerTwo invoked ....."); 
   } 
  },2000,500,TimeUnit.MILLISECONDS); 
 } 
  
 public static void main(String[] args) { 
  ScheduledExecutorTest test = new ScheduledExecutorTest(); 
  test.timerOne(); 
  test.timerTwo(); 
 } 
} 

運轉成果:

timerTwo invoked ..... 
timerTwo invoked ..... 
timerTwo invoked ..... 
timerTwo invoked ..... 
timerTwo invoked ..... 
timerTwo invoked ..... 
timerTwo invoked ..... 
timerTwo invoked ..... 
timerTwo invoked ..... 
........................ 


4、應用准時器完成彈彈球
模仿書上的一個例題做了一個彈彈球,是在畫布上的指定地位畫多個圓,經由一段的延時後,在鄰近地位從新畫。使球看起來是動,經由過程JSpinner組件調理延時,來掌握彈彈球的挪動速度.
        BallsCanvas.java

public class BallsCanvas extends Canvas implements ActionListener, 
  FocusListener { 
 
 private Ball balls[]; // 多個球 
 private Timer timer; 
 
 private static class Ball { 
  int x, y; // 坐標 
  Color color; // 色彩 
  boolean up, left; // 活動偏向 
 
  Ball(int x, int y, Color color) { 
   this.x = x; 
   this.y = y; 
   this.color = color; 
   up = left = false; 
  } 
 } 
 
 public BallsCanvas(Color colors[], int delay) { // 初始化色彩、延時 
  this.balls = new Ball[colors.length]; 
  for (int i = 0, x = 40; i < colors.length; i++, x += 40) { 
   balls[i] = new Ball(x, x, colors[i]); 
  } 
  this.addFocusListener(this); 
  timer = new Timer(delay, this); // 創立准時器對象,delay指定延時 
  timer.start(); 
 
 } 
 
 // 設置延時 
 public void setDelay(int delay) { 
  timer.setDelay(delay); 
 } 
 
 // 在canvas下面作畫 
 public void paint(Graphics g) { 
  for (int i = 0; i < balls.length; i++) { 
   g.setColor(balls[i].color); // 設置色彩 
   balls[i].x = balls[i].left ? balls[i].x - 10 : balls[i].x + 10; 
   if (balls[i].x < 0 || balls[i].x >= this.getWidth()) { // 到程度偏向更改偏向 
    balls[i].left = !balls[i].left; 
   } 
 
   balls[i].y = balls[i].up ? balls[i].y - 10 : balls[i].y + 10; 
   if (balls[i].y < 0 || balls[i].y >= this.getHeight()) { // 到垂直偏向更改偏向 
    balls[i].up = !balls[i].up; 
   } 
   g.fillOval(balls[i].x, balls[i].y, 20, 20); // 畫指定直徑的圓 
  } 
 } 
 
 // 准時器准時履行事宜 
 @Override 
 public void actionPerformed(ActionEvent e) { 
  repaint(); // 重畫 
 } 
 
 // 取得核心 
 @Override 
 public void focusGained(FocusEvent e) { 
  timer.stop(); // 准時器停滯 
 
 } 
 
 // 掉去核心 
 @Override 
 public void focusLost(FocusEvent e) { 
  timer.restart(); // 准時重視啟動 
 
 } 
} 

BallsJFrame.java

class BallsJFrame extends JFrame implements ChangeListener { 
 
  private BallsCanvas ball; 
  private JSpinner spinner; 
 
  public BallsJFrame() { 
   super("彈彈球"); 
   this.setBounds(300, 200, 480, 360); 
   this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
   Color colors[] = { Color.red, Color.green, Color.blue, 
     Color.magenta, Color.cyan }; 
   ball = new BallsCanvas(colors, 100); 
   this.getContentPane().add(ball); 
 
   JPanel panel = new JPanel(); 
   this.getContentPane().add(panel, "South"); 
   panel.add(new JLabel("Delay")); 
   spinner = new JSpinner(); 
   spinner.setValue(100); 
   panel.add(spinner); 
   spinner.addChangeListener(this); 
   this.setVisible(true); 
  } 
 
  @Override 
  public void stateChanged(ChangeEvent e) { 
   // 修正JSpinner值時,單擊JSpinner的Up或許down按鈕時,或許在JSpinner中按Enter鍵 
   ball.setDelay(Integer.parseInt("" + spinner.getValue())); 
 
  } 
 
 public static void main(String[] args) { 
  new BallsJFrame(); 
 } 
 
} 

後果以下:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved