Wait()、Notify()、定时器和 Jbuttons

Posted

技术标签:

【中文标题】Wait()、Notify()、定时器和 Jbuttons【英文标题】:Wait(), Notify(), timers and Jbuttons 【发布时间】:2013-06-08 03:56:33 【问题描述】:

我什至不知道如何解决这个问题,但是在阅读了一些内容并进行了很多尝试(失败)之后,我决定向社区寻求帮助。我有表单 A 打开并要求用户输入延迟表单 B 打开的时间。目前我正在使用sleep() 来执行此操作,但现在我想插入另一个对话框以允许用户在计时器用完之前中断计时器并调出表单 B。我相信正确的方法是使用wait()notify(),但我似乎无法理解生产者和消费者模型的众多示例。任何帮助表示赞赏。

【问题讨论】:

不要阻塞 EDT(事件调度线程)——当这种情况发生时,GUI 将“冻结”。而不是调用Thread.sleep(n) 为延迟任务实现Swing Timer。有关详细信息,请参阅Concurrency in Swing。 【参考方案1】:

javax.swing.Timer 的完美工作。详情请参阅How to Use Swing Timers。这是一个示例,可引导您朝着正确的方向前进。

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

public class TimerDemo extends JFrame implements ActionListener 

    private Timer timer;
    private JButton jbDoSomethingDelayed;
    private JButton jbDoItImmediately;

    public TimerDemo()         
        setLayout(new FlowLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Timer demo");

        jbDoSomethingDelayed = new JButton("Do something with a delay");
        jbDoItImmediately = new JButton("Do it. Do it NOW!");

        add(jbDoSomethingDelayed);
        add(jbDoItImmediately);

        jbDoItImmediately.setEnabled(false);

        timer = new Timer(0, this); // we override delay later
        timer.setRepeats(false); // we don't want it firing repeatedly

        jbDoSomethingDelayed.addActionListener(new ActionListener() 
            public void actionPerformed(ActionEvent e) 
                String msg = "Enter delay and confirm dialog";
                JSpinner spinner = new JSpinner(new SpinnerNumberModel(5, 1, 10, 1));
                Object[] content = new Object[] msg, spinner;
                int showConfirmDialog = JOptionPane.showConfirmDialog(TimerDemo.this, content, "Choose", JOptionPane.OK_CANCEL_OPTION);
                if (showConfirmDialog == JOptionPane.OK_OPTION) 
                    // the important part
                    timer.setInitialDelay(((Integer)spinner.getValue()) * 1000);                    
                    jbDoSomethingDelayed.setEnabled(false);
                    jbDoItImmediately.setEnabled(true);
                    timer.start();
                
            
        );

        jbDoItImmediately.addActionListener(new ActionListener() 
            public void actionPerformed(ActionEvent e) 
                timer.stop();
                onTimerTimeout();
            
        );

        pack();
        setLocationRelativeTo(null);
    

    public void actionPerformed(ActionEvent e) 
        // called by timer on EDT, no worries here
        onTimerTimeout();
    

    private void onTimerTimeout()    
        jbDoSomethingDelayed.setEnabled(true);
        jbDoItImmediately.setEnabled(false);
        JOptionPane.showConfirmDialog(this, "You've done it now. No, really...", "It is done", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE);        
    

    public static void main(String[] args) 
        EventQueue.invokeLater(new Runnable() 
            public void run() 
                TimerDemo demo = new TimerDemo();
                demo.setVisible(true);
            
        );
    

【讨论】:

【参考方案2】:

最简单的方法是做这样的事情

Thread a = new Thread(new Runnable()
   public void run()
      //do whatever display
      try
        Thread.sleep(timeToShowBform);
      
      catch(InterruptedException ex)
         //interrupted.
      finally
      //show form B
      SwingUtilities.invokeLater(...)

   
);

class BRunnable implements Runnable
public void run()
 //if clicked, then this runnable is called.
 a.interrupt();


线程a 假设在sleep 被阻塞,然后在调用a.interrupt() 时唤醒a

【讨论】:

这将在 EDT 之外显示表单,这可能不是一个好主意。 @assylias 是的,这就是为什么我在上面使用Thread 来代替a 而不仅仅是可运行的。 我的意思是 finally 块将在该线程上执行,而不是在 EDT 上。并且您应该只与 EDT 中的 GUI 进行交互。

以上是关于Wait()、Notify()、定时器和 Jbuttons的主要内容,如果未能解决你的问题,请参考以下文章

JAVA笔记(20)--- 死锁;如何解决线程安全问题;守护线程;定时器;Callable 实现线程;wait ( ) 和 notify ( ) ;实现生产者和消费者模式;

wait和notify

为啥wait,notify和notifyAll必须在同步块或同步方法中调

[多线程]wait和notify

java同步中,为啥要wait,又notify谁?

JUC并发编程 -- 为什么需要wait/notify方法 & 原理之 wait / notify & wait() 和 notify() API介绍