Java - 在后台线程中处理计时器事件

时间:2010-12-16 09:42:24

标签: java multithreading events

我在这里有这个计时器:

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),因此生产者将永久生成消息。 我遇到的问题是它阻塞了系统,因此系统停止响应。

有什么方法可以在后台线程中触发此事件吗?

谢谢, 奥斯卡

3 个答案:

答案 0 :(得分:3)

您可以在线程中启动doWork():

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

答案 1 :(得分:2)

javax.swing.Timer在事件派发线程上执行ActionListener回调。这意味着您的代码必须快速返回,否则GUI将冻结。

如果要在其他线程上运行此任务,可以考虑使用java.util.Timer类。与每次调用Thread doWork时产生新Thread相比,这将更加清晰,资源消耗更少(创建新的{{1}}是昂贵的。)

答案 2 :(得分:0)

我会创建一些事件对象的同步队列(LinkedBlockingQueue是一个很好的例子)。然后timer事件只是将一个对象放入队列,处理线程将从队列中取出()对象,并在下一个对象可用时进行处理(take()自动等待它。)