Java 阻止线程摆动的计时器

Java 阻止线程摆动的计时器,java,swing,timer,Java,Swing,Timer,我试图用Java制作一个计时器应用程序,但在计数过程中,它不会执行main(也会打开窗口),直到计数器完成。 这就是我的意思: long timeElapsed = 0; long timeStart = System.currentTimeMillis(); for (long counter=0;counter<5;++counter) { TimeUnit.SECONDS.sleep(1); timeElapsed = (System.

我试图用Java制作一个计时器应用程序,但在计数过程中,它不会执行main(也会打开窗口),直到计数器完成。 这就是我的意思:

long timeElapsed = 0;
    long timeStart = System.currentTimeMillis();
    for (long counter=0;counter<5;++counter) {
        TimeUnit.SECONDS.sleep(1);
        timeElapsed = (System.currentTimeMillis() - timeStart)/1000;
        display.setText(Long.toString(timeElapsed));
    }
    String myString = Long.toString(timeElapsed);

注意:我还没有使用程序的按钮部分,而且我试图修复的代码在方法
Initialize()

欢迎来到“亲爱的,我阻止了事件调度线程”的精彩世界

Swing是单线程的,并且不是线程安全的。这意味着,如果您通过执行类似于
Thread.sleep
的操作来阻止事件调度线程,则UI将无法更新,因为您已阻止负责更新它的线程

同样,您不应该从EDT上下文之外更新UI或UI所依赖的任何内容,这给您留下了一个难题

幸运的是,Swing开发人员预见到了这个问题,并提供了许多可能的解决方案,在您的情况下,最好的可能是旧的Swing
定时器

首先,查看和了解更多详细信息


我还应该添加,
Timer
s(和
Thread.sleep
)在本质上是不准确的,只能保证“至少”准确。与其使用计数器来跟踪它们运行了多长时间,不如使用
java.time
API来代替,

欢迎来到“亲爱的,我阻止了事件调度线程”的精彩世界

Swing是单线程的,并且不是线程安全的。这意味着,如果您通过执行类似于
Thread.sleep
的操作来阻止事件调度线程,则UI将无法更新,因为您已阻止负责更新它的线程

同样,您不应该从EDT上下文之外更新UI或UI所依赖的任何内容,这给您留下了一个难题

幸运的是,Swing开发人员预见到了这个问题,并提供了许多可能的解决方案,在您的情况下,最好的可能是旧的Swing
定时器

首先,查看和了解更多详细信息


我还应该添加,
Timer
s(和
Thread.sleep
)在本质上是不准确的,只能保证“至少”准确。您不应该使用计数器来跟踪它们运行了多长时间,而应该使用
java.time
API,您可以参考以下链接:

在该方法中,您可以使用经过的时间更新UI组件(例如JLabel)


您可以参考以下链接:

在该方法中,您可以使用经过的时间更新UI组件(例如JLabel)


好的,谢谢,我稍后会查看这是我的第一次尝试,所以我有点像是在黑暗中拍摄的,但是谢谢你参考一些资料来源。是的,我注意到定时器模块在每次计数时都会关闭几百毫秒左右。Thread.sleep是如何阻止它的?它是否占用线程?
thread.sleeps
停止当前正在运行的线程,这意味着事件调度线程在离开该方法之前无法处理事件队列-因此,即使是长时间运行的循环也会产生效果如果我制作一个按钮来触发它,我是否必须使用一个方法来执行此操作,或者还有其他更有效的方法吗?这个按钮需要一个ActionListener,但基本的想法是,在某个时候,你需要准时调用start。谢谢你,我稍后会检查它。这是我第一次尝试,所以我有点摸不着头脑,但感谢你参考了一些资料。是的,我注意到定时器模块在每次计数时都会关闭几百毫秒左右。Thread.sleep是如何阻止它的?它是否占用线程?
thread.sleeps
停止当前正在运行的线程,这意味着事件调度线程在离开该方法之前无法处理事件队列-因此,即使是长时间运行的循环也会产生效果如果我制作一个按钮来触发它,我是否必须使用一个方法来执行此操作,或者还有其他更有效的方法吗?这个按钮需要一个ActionListener,但基本的想法是,在某个时候,你需要在计时器上调用start
import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.util.concurrent.TimeUnit;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JButton;

public class TimerGUI {

    private JFrame frame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    TimerGUI window = new TimerGUI();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     * @throws InterruptedException 
     */
    public TimerGUI() throws InterruptedException {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     * @throws InterruptedException 
     */
    private void initialize() throws InterruptedException {
        JLabel display = new JLabel("a");
        // TIME
        long timeElapsed = 0;
        long timeStart = System.currentTimeMillis();
        for (long counter=0;counter<5;++counter) {
            TimeUnit.SECONDS.sleep(1);
            timeElapsed = (System.currentTimeMillis() - timeStart)/1000;
            display.setText(Long.toString(timeElapsed));
        }
        String myString = Long.toString(timeElapsed);


        //WINDOW
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);

        // LABEL
        //display = new JLabel(myString);
        display.setBounds(165, 64, 89, 54);
        frame.getContentPane().add(display);


        //BUTTON
        JButton btnNewButton = new JButton("New button");
        btnNewButton.setBounds(165, 169, 89, 32);
        frame.getContentPane().add(btnNewButton);



    }
}