线程休眠和线程连接

时间:2010-12-30 10:45:49

标签: java multithreading

如果我把一个线程放在一个循环中睡觉,netbeans给我一个警告说循环调用Thread.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等待其他线程完成,但在这种情况下,不是睡觉和加入做同样的事情?那为什么netbeans会引起注意呢?

3 个答案:

答案 0 :(得分:30)

join()和sleep()之间存在差异。 join()将等待超时到期或线程完成。 sleep()只会等待指定的时间,除非被打断。因此,join()返回的速度比指定时间快得多。

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

答案 1 :(得分:5)

他们可以用来实现同样的事情并不意味着他们以同样的方式被滥用。人们经常滥用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;

答案 2 :(得分:1)

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

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

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

lock sample:调用线程代码;

Object lock = 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();
      } 

   }