【问题标题】:Thread sleep and thread join线程休眠和线程连接
【发布时间】:2011-06-01 12:12:38
【问题描述】:

如果我让一个线程在循环中休眠,netbeans 会提醒我在循环中调用 Thread.sleep 会导致性能问题。但是,如果我用 join 替换 sleep,则不会给出这样的警告。两个版本都可以编译并正常工作。我的代码如下(检查最后几行“Thread.sleep() vs t.join()”)。

public class Test{

    //Display a message, preceded by the name of the current thread
    static void threadMessage(String message) {
        String threadName = Thread.currentThread().getName();
        System.out.format("%s: %s%n", threadName, message);
    }

    private static class MessageLoop implements Runnable {
        public void run() {
            String importantInfo[] = {
                "Mares eat oats",
                "Does eat oats",
                "Little lambs eat ivy",
                "A kid will eat ivy too"
            };
            try {
                for (int i = 0; i < importantInfo.length; i++) {
                    //Pause for 4 seconds
                    Thread.sleep(4000);
                    //Print a message
                    threadMessage(importantInfo[i]);
                }
            } catch (InterruptedException e) {
                threadMessage("I wasn't done!");
            }
        }
    }

    public static void main(String args[]) throws InterruptedException {


        //Delay, in milliseconds before we interrupt MessageLoop
        //thread (default one hour).
        long patience = 1000 * 60 * 60;

        //If command line argument present, gives patience in seconds.
        if (args.length > 0) {
            try {
                patience = Long.parseLong(args[0]) * 1000;
            } catch (NumberFormatException e) {
                System.err.println("Argument must be an integer.");
                System.exit(1);
            }

        }

        threadMessage("Starting MessageLoop thread");
        long startTime = System.currentTimeMillis();
        Thread t = new Thread(new MessageLoop());
        t.start();

        threadMessage("Waiting for MessageLoop thread to finish");
        //loop until MessageLoop thread exits
        while (t.isAlive()) {
            threadMessage("Still waiting...");
            //Wait maximum of 1 second for MessageLoop thread to
            //finish.
            /*******LOOK HERE**********************/
            Thread.sleep(1000);//issues caution unlike t.join(1000)
            /**************************************/
            if (((System.currentTimeMillis() - startTime) > patience) &&
                    t.isAlive()) {
                threadMessage("Tired of waiting!");
                t.interrupt();
                //Shouldn't be long now -- wait indefinitely
                t.join();
            }

        }
        threadMessage("Finally!");
    }
}

据我了解,join 等待另一个线程完成,但在这种情况下,sleep 和 join 都不是在做同样的事情吗?那为什么netbeans会抛出这个警告呢?

【问题讨论】:

  • 这个stackoverflow.com/questions/3535754/… 可能会有所帮助
  • @prateek 是的,我实际上在发布之前就看到了该线程。但是,这个问题是一个完全不同的问题(我知道谨慎的原因,但不知道为什么在这种情况下会这样做)。感谢您的意见!非常感谢!

标签: java multithreading


【解决方案1】:

它们可用于实现相同的目标并不意味着它们以相同的方式被滥用。人们在真正应该使用锁或阻塞的东西时经常滥用Thread.sleep()

 // Allow others to notify me when there's work to do
 synchronized (lock) {
     try {
         lock.wait(); // Much better than a loop with sleep
     } catch(InterruptedException e) {
         // someone killed me
         return;
     }
 }


 // or use a BlockingQueue or similar
 Job job = queue.get();
 if (job instanceof ExitJob) return;

【讨论】:

  • 感谢您的帮助!我想那我的 qn 会是这样的——睡眠和加入之间有什么区别?在这种情况下,对我来说似乎没有..
  • 在你的情况下,没有区别; Netbeans 只是对sleep() 发出警告。
  • 嗯,“锁定”是指睡眠,对吧? “更好的选择”是指在这种特定情况下更好的选择,对吧?
  • 通过锁定,我的意思是您在其上创建Objectwait 的实例,直到有人调用notify。这样,您就不会浪费时间无所事事。如果您需要重复执行某项操作,请使用Timer 而不是等待自己。
  • @AaronDigulla Timer 不应从 Java 5 开始使用。更好的选择是使用 ScheduledThreadPoolExecutor ...
【解决方案2】:

对于这种情况,我认为连接比使用锁更好。连接简单而优雅。但是如果你使用锁,你也应该使用 notify 方法和同步块,当然你需要一个锁对象..

加入样本,调用线程代码;

t1.start();
System.out.println("waiting for thread t1");
t1.join();
System.out.println("thread t1 has finished its job");

锁示例:调用线程代码;

对象锁 = new Object();

 synchronized(lock) {
  try {
      t1.start();
      System.out.println("waiting for thread t1");
       lock.wait();
      System.out.println("thread t1 has finished its job");
  }catch (InterruptedException ex) {
          e.printStackTrace();
  } 

}

这里是线程t1代码;

 synchronized(lock) {
      try {
          System.out.println("doing heavy work");
           // .....
            lock.notify();
          }catch (InterruptedException ex) {
              e.printStackTrace();
      } 

   }

【讨论】:

  • 感谢您的帮助 Gursel,非常感谢。我同意,锁肯定更好。但我的 qn 是在睡眠和加入,并且在这种特定情况下两者的功能相同。
【解决方案3】:

join() 和 sleep() 是有区别的。 join() 将等到超时到期或线程完成。 sleep() 只会等待指定的时间,除非被中断。所以 join() 完全有可能比指定的时间快得多。

Netbeans 警告您关于 sleep() 而不是关于 join() 的原因正是这种差异。 join() 等待有意义的事情,而 sleep() 只是坐在那里什么都不做。如果你不等待某事,那你为什么要等待呢?它很少有意义,因此发出警告。

【讨论】:

  • 啊,我明白了!我相信这是正确回答我的问题的唯一答案。感谢您的帮助谢尔盖!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 2015-11-05
  • 1970-01-01
  • 1970-01-01
  • 2019-08-12
  • 1970-01-01
相关资源
最近更新 更多