Thread.sleep()

时间:2016-10-04 16:39:02

标签: java multithreading thread-sleep coding-efficiency

我这里有一些代码,就像我想要的那样。它只是在我在代码中确定的特定日期的秒数倒计时。我使用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方法调用的方法调用的方法。此方法最终将秒剩余变量发送到第3个方法:

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的方法(由上面的方法调用):

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);
}

我不包括剩下的代码,因为它应该是无关紧要的,但如果你想看到它,请告诉我。

3 个答案:

答案 0 :(得分:3)

两个问题:

  1. 您正在从后台线程调用text.setSomething()panel.add,后台线程不是您应该使用的UI线程。尝试使用SwingUtils.invokeLater()SwingUtils.invokeAndWait()并调用触及那里UI的代码。

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

答案 1 :(得分:1)

您应该只在事件循环中更新GUI组件。如果您尝试在其他线程中更新它们,则可能会得到不可预测的结果。我建议在GUI事件循环中使用swing Timer来定期执行任务。

答案 2 :(得分:0)

您可以尝试使用var Flickr = require("flickrapi"); var FlickCred = require("./flickrAuthCred"); var flickrOptions = FlickCred; Flickr.authenticate(flickrOptions, function(error, flick){ if(error){ console.log("Error!"); console.log(error); return; } var photosReqOptions = { user_id: "132868185@N07", extras: ["owner_name", "date_taken", "date_upload", "path_alias"] } flick.people.getPhotosOf(photosReqOptions, function(error, data){ console.log(data.photos); }); });

它有一个方法Timer,它将接受要执行的任务,开始执行任务的时间以及应该从中运行任务的时间间隔。

将计划的操作包装到扩展#scheduleAtFixedRate的类中,以便与此方法一起使用。

以下是Java 7 https://docs.oracle.com/javase/7/docs/api/java/util/Timer.html

中此类的javadoc