Java Thread.sleep()的效率

Java Thread.sleep()的效率,java,multithreading,thread-sleep,coding-efficiency,Java,Multithreading,Thread Sleep,Coding Efficiency,我这里有一些代码,它的工作方式与我所希望的一样。所有这些都是我在代码中确定的某个特定日期的倒数,以秒为单位。我正在使用Thread.currentThread().sleep(1000)以当前时间更新JLabel,直到日期。问题是JLabel并不像预期的那样每秒刷新一次。有时每2秒更新一次,有时则需要整整10秒才能更新。我相信这与我如何调用我的方法有关,但我不太确定如何使它更有效 以下是调用该方法以更新线程内JLabel的主要方法: public static void main(String

我这里有一些代码,它的工作方式与我所希望的一样。所有这些都是我在代码中确定的某个特定日期的倒数,以秒为单位。我正在使用
Thread.currentThread().sleep(1000)
以当前时间更新JLabel,直到日期。问题是JLabel并不像预期的那样每秒刷新一次。有时每2秒更新一次,有时则需要整整10秒才能更新。我相信这与我如何调用我的方法有关,但我不太确定如何使它更有效

以下是调用该方法以更新线程内JLabel的主要方法:

public static void main(String args[])
{
    initUI();
    try
    {
        while(true)
        {
            Thread.currentThread().sleep(1000);
            getTime();
        }
    } catch(Exception e){System.out.println("An error has occured...");}
}
这里是由main方法调用的方法调用的方法。此方法最终将剩余秒数变量发送到第三个方法:

public static void getTime()
{
    Calendar c = Calendar.getInstance();
    // Gets abstract current time in ms
    long now = c.getTimeInMillis();

    c.set(Calendar.HOUR_OF_DAY, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    c.set(Calendar.MILLISECOND, 0);

    // Gets current time in ms
    long msPassed = now - c.getTimeInMillis();
    // There are 86,400,000 milliseconds in a day
    // Gets the seconds remaining in the day
    long secRemaining = (86400000 - msPassed) / 1000;

    //-----------------------------------------------------// 
    // Creates a new calendar for today
    Calendar cal = Calendar.getInstance();
    int currentDayOfYear = cal.get(Calendar.DAY_OF_YEAR);

    // Creates a calendar for November 20th, 2016
    Calendar aniv = new GregorianCalendar(2016,10,20);
    aniv.set(Calendar.MONTH, 10);
    aniv.set(Calendar.DAY_OF_MONTH, 20);
    int aniversary = aniv.get(Calendar.DAY_OF_YEAR);

    remaining = ((aniversary - currentDayOfYear) * 24 * 60 * 60) + secRemaining;
    setTextOnScreen(remaining);
}
最后,这是重写JLabel的方法(由上面的方法调用):


我不包括代码的其余部分,因为它应该是无关的,但是如果您也想看到它,请告诉我

您应该只更新事件循环中的GUI组件。如果您尝试在其他线程中更新它们,可能会得到不可预知的结果。我建议对GUI事件循环中要运行的定期任务使用swing计时器。

您应该只更新事件循环中的GUI组件。如果您尝试在其他线程中更新它们,可能会得到不可预知的结果。我建议对GUI事件循环中要运行的定期任务使用swing计时器。

两个问题:

  • 您正在调用
    text.setSomething()
    面板。从后台线程添加
    ,该线程不是您应该使用的UI线程。尝试使用
    SwingUtils.invokeLater()
    SwingUtils.invokeAndWait()
    并调用与UI接触的代码

  • 在调用
    set
    方法之后,还应该调用
    text.invalidate()
    来表示需要更新UI组件。。。否则UI线程不会注意到组件需要重新测量和重新绘制

  • 两个问题:

  • 您正在调用
    text.setSomething()
    面板。从后台线程添加
    ,该线程不是您应该使用的UI线程。尝试使用
    SwingUtils.invokeLater()
    SwingUtils.invokeAndWait()
    并调用与UI接触的代码

  • 在调用
    set
    方法之后,还应该调用
    text.invalidate()
    来表示需要更新UI组件。。。否则UI线程不会注意到组件需要重新测量和重新绘制


  • 您可以尝试使用
    计时器

    它有一个方法
    #scheduleAtFixedRate
    ,该方法将接受要执行的任务、开始执行任务的时间以及运行任务的时间间隔

    将计划的操作包装到一个类中,该类扩展了
    TimerTask
    ,可用于此方法


    以下是Java 7中该类的javadocs,您可以尝试使用
    计时器

    它有一个方法
    #scheduleAtFixedRate
    ,该方法将接受要执行的任务、开始执行任务的时间以及运行任务的时间间隔

    将计划的操作包装到一个类中,该类扩展了
    TimerTask
    ,可用于此方法


    以下是Java 7中该类的javadocs

    您的睡眠时间为2秒您的睡眠时间为2秒
    public static void setTextOnScreen(long num)
    {
        text.setForeground(Color.GREEN);
        text.setLocation((int)width/2 - 150, 50);
        text.setFont(new Font("Monospaced", Font.BOLD, 48));
        text.setSize(300,150);
    
        text.setText("" + num);
        panel.add(text);
    }