Thread.sleep(1)卡在线程转储中

时间:2017-11-14 12:58:41

标签: java multithreading

我正在使用JRocket1.6。在线程转储中,我看到了

"Thread-174" id=994 idx=0xb54 tid=1012 prio=10 alive, sleeping, native_waiting
    at java/lang/Thread.sleep(J)V(Native Method)
    at com/test/EraserThread.run(EraserThread.java:50)
    at java/lang/Thread.run(Thread.java:662)
    at jrockit/vm/RNI.c2java(JJJJJ)V(Native Method)
    -- end of trace

这个帖子被卡住了,永远不会被释放。

代码:

public static String readAndMaskPassword( BufferedReader reader, PrintWriter writer){
         //Starting the masking thread for the password entered
           EraserThread et = new EraserThread(writer);
           Thread mask = new Thread(et);
           mask.start();

           String password = "";

           try {
              password = reader.readLine();
           } catch (IOException ioe) {
             ioe.printStackTrace();
           }
           // stop masking
           et.stopMasking();
           // return the password entered by the user
           return password;
       }

readAndMaskPassword方法返回输入的密码,并正确返回此方法。

EraserThread.java :

public void run() {
        int priority = Thread.currentThread().getPriority();
            Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
        try{
            while (start) {
                writer.print("\b ");
                writer.flush();
                try {
                    Thread.sleep(1);
                } catch (InterruptedException ie) {
                    _logger.error(ie.getMessage(),ie);
                }
            }           
        }finally{
            //Restore the original priority 
            Thread.currentThread().setPriority(priority);
        }
    }

    public void stopMasking() {
        this.start = false;
    }
正在调用

stopMasking方法,start设置为false。我很困惑为什么EraserThread因为线程转储而被卡在Thread.sleep(1)

请求你的帮助。

1 个答案:

答案 0 :(得分:1)

它实际上并没有被卡住。只是在你检查线程的堆栈跟踪时,它更有可能执行睡眠调用。

writer.printwriter.flush的调用平均需要几分之一毫秒。所以,如果我们假装为了说明每个方法需要0.01毫秒,那么循环执行的时间分配如下所示:

writer.print    0.01 ms
writer.flush    0.01 ms
Thread.sleep    1.00 ms

正如您所看到的,每当您要求进行线程转储时,与其他方法相比,执行sleep的几率要大得多。

另外需要注意:您的try / catch应该在外面 while循环。当你的循环被写入时,它会忽略中断,这使它成为一个流氓线程 - 一个无法停止的线程。线程不能被“杀死”;它们只能被中断,并且每个线程都有责任正确地清理和退出以响应中断。

简单的解决方案是将你的while循环移到你的try / catch中

try {
    while (start) {
        writer.print("\b ");
        writer.flush();
        Thread.sleep(1);
    }           
} catch (InterruptedException ie) {
    _logger.error(ie.getMessage(), ie);
}

这意味着,如果您愿意,可以取消使用start变量(并改为使用while (true)),然后取消使用stopMasking方法,而不是只需中断线程就可以阻止它:

mask.interrupt();

(我再说一遍,因为你的代码是当前编写的,调用mask.interrupt()实际上什么都不做。)