2010-12-16 47 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()自动等待)。