2010-12-16 45 views
0

我有這個計時器在這裏:爪哇 - 在後臺線程處理定時器事件

timer = new Timer(delay, new ActionListener() {   
     @Override 
     public void actionPerformed(ActionEvent e) { 
      try { 
       doWork(); 
      } catch (JMSException e1) { 
       e1.printStackTrace(); 
      }    
     } 
    }); 
    timer.start(); 

調用此代碼:

public void doWork() throws JMSException { 
    String fileContent = getFileContent(); 
    Session session = queue.getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE); 

    Destination dest = session.createQueue(queue.getName()); 
    MessageProducer producer = session.createProducer(dest); 
    TextMessage message = session.createTextMessage(); 

    //Different and not less than to be able to create permanent producers 
    for (int i = 0; i != numberOfMsgsInBurst; i++) { 
     message.setText(fileContent); 
     producer.send(message); 
    } 

    /* 
    * Send a non-text control message indicating end of messages. 
    */ 
    producer.send(session.createMessage());  
} 

至於我遇到,當的doWork被稱爲定時器,它會阻塞系統(例如GUI)。我希望能夠永久運行此doWork方法(將numberOfMsgsInBurst設置爲-1),以便生產者永久生成消息。 我遇到的問題是它阻塞系統,所以系統停止響應。

有什麼辦法可以在後臺線程中觸發這個事件嗎?

感謝, 奧斯卡

回答

2

javax.swing.Timer s在事件分派線程上執行ActionListener回調。這意味着您的代碼必須快速返回,否則GUI將凍結。

如果你想在不同的線程上運行這個任務,你可以考慮使用java.util.Timer類。與每產生一個新的Thread產生一個新的Thread相比,這將會更清潔和更少的資源密集度(創建新的Thread很昂貴)。

+0

這可能是最好的方法。我不知道java.util.Timer。 – 2010-12-16 09:56:57

3

您可以在一個線程啓動的doWork():

public void actionPerformed(ActionEvent e) { 
    Thread t = new Thread() { 
     @Override 
     public void run() { 
      try { 
      doWork(); 
      } catch (JMSException e1) { 
      e1.printStackTrace(); 
      } 
     } 
    }; 
    t.start(); 
} 
+0

這有一個缺點,每次事件觸發時都會啓動一個新線程。否則一個好的解決方案 – 2010-12-16 09:52:23

+0

確實如此,但據我瞭解,doWork()可能會無限運行。 – morja 2010-12-16 09:54:47

+0

是的,它可能在某些情況下運行無窮(用戶可能會定義它是否應該運行給定次數的迭代或無休止地) – JSBach 2010-12-16 09:58:31

0

我會做一個同步隊列(的LinkedBlockingQueue是一個很好的例子)的一些事件的對象。然後,計時器事件只會將一個對象放入隊列中,處理線程將從隊列中取出()對象,並在下一個對象可用時執行處理(take()自動等待)。