5

我仍然是Java的初學者,所以我沒有學到太多有關線程和併發的知識。不過,我希望能夠使用ScheduledThreadPoolExecutor作爲定時器,因爲我使用java.util.Timer和TimerTask時遇到了問題。我對創建線程非常感興趣,並且知道我將在幾周內瞭解它們。然而,如果可能的話,有人可以給我一個關於如何使用util.timer將當前迷你測試程序轉換爲使用ScheduledThreadPoolExecutor的基本示例?轉換爲ScheduledThreadPoolExecutor

我想盡快完成這個例子,所以我沒有太多時間瞭解線程 - 無論我想多少。說了這個之後,請包括任何你認爲對於ScheduledThreadPoolExecutor來說Java初學者應該知道的重要東西。

實施例程序

我已經作出一個快速的小例子來表示我在一個更大的程序具有的問題。這個程序應該做的是讓用戶按下一個按鈕來啓動一個計數器。當有需要時,用戶必須能夠停止並重啓計數器。在較大的程序中,這個計數器保持相等是很重要的,所以我已經使用了 scheduleAtFixRate() 方法。初始延遲始終相同(在此情況下爲0)也很重要。 問題(我相信你會看到)是一旦定時器被取消,它不能重新啓動 - 我希望ScheduledThreadPoolExecutor可以解決的問題。

代碼:

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.util.TimerTask; 
import java.util.Timer; 

public class Tester extends JFrame { 
    JButton push = new JButton("Push"); 
    static JTextArea textOut = new JTextArea(); 
    Timer timer = new Timer(); 
    boolean pushed = false; 
    static int i = 1; 

    public Tester() { 
     super(); 
     add(push, BorderLayout.NORTH); 
     add(textOut); 
     push.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       if (!pushed) { 
        timer.scheduleAtFixedRate(new Task(), 0, 1000); 
        pushed = true; 
       } else { 
        timer.cancel(); 
        pushed = false; 
       } 
      } 
     }); 
    } 

    static class Task extends TimerTask { 
     public void run() { 
      textOut.setText("" + i++); 
     } 
    } 

    public static void main(String[] args) { 
     Tester a = new Tester(); 
     a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     a.pack(); 
     a.setVisible(true); 
    } 
} 

我使用這個類很多關於測試因此可能會有額外的代碼(我認爲我刪除了這一切)。

+2

我覺得你提了編寫代碼你...想學習線程的一個路人皆知的幌子,「我想盡快完成這個例子,所以我沒有太多時間去學習線程 - 不管我有多想。「 –

+0

通常,一個學習示例不包含「它至關重要」等字樣。 – SJuan76

+0

我希望沒有人會這麼想。我對編程充滿熱情,並且正在大學學習。如果我想讓人們編寫我的程序,我會將實際代碼放在示例中,而不是我做的一個快速測試示例。 –

回答

23

更換

Timer timer = new Timer(); 

ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 

class Task extends TimerTask 

class Task implements Runnable 

timer.scheduleAtFixedRate(new Task(), 0, 1000); 

service.scheduleAtFixedRate(new Task(), 0, 1000, TimeUnit.MILLISECONDS); 

BTW你不應該試圖更新另一個線程的GUI。相反,你必須將任務添加到了Swing GUI線程來執行任務

SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      textOut.setText("" + i++); 
     } 
    }); 
+4

用於提及GUI線程。 – mrab

+0

儘管如此,仍然會添加死線。我得到了'pool - ## - thread-1',他們從來沒有被清理過。我錯過了什麼嗎? – kmort

+0

@kmort我假設你在完成時沒有執行shutdown()。 –