Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程-start()和run()-控制台中的行丢失_Java_Multithreading - Fatal编程技术网

Java线程-start()和run()-控制台中的行丢失

Java线程-start()和run()-控制台中的行丢失,java,multithreading,Java,Multithreading,为什么下面场景1中缺少另一个“taskinpl run()” 场景1:如果行标记为1。在标有2的行之前。这在控制台中显示: taskinpl run() ThreadImpl run() ThreadImpl run() 完成 场景2:如果标记为2的行。在标有1的行之前。这在控制台中显示: taskinpl run() taskinpl run() ThreadImpl run() ThreadImpl run() 完成 我的代码: public class ThreadTest { p

为什么下面场景1中缺少另一个“taskinpl run()”

场景1:如果行标记为1。在标有2的行之前。这在控制台中显示:

taskinpl run()
ThreadImpl run()
ThreadImpl run()
完成

场景2:如果标记为2的行。在标有1的行之前。这在控制台中显示:

taskinpl run()
taskinpl run()
ThreadImpl run()
ThreadImpl run()
完成

我的代码:

public class ThreadTest {
    public static void main(String[] args) 
    {
        Thread t1 = new ThreadImpl();
        Thread t2 = new Thread(new TaskImpl());

        t1.start();
        t2.start();

        t1.run();   // 1.
        t2.run();   // 2. 

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("Finished");
    }
}

class ThreadImpl extends Thread {
    @Override
    public void run() {
        try {
            Thread.sleep(2000);
            System.out.println("ThreadImpl run()");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

class TaskImpl implements Runnable {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
            System.out.println("TaskImpl run()");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

正如您在
target
run
方法的实现中所看到的(应该在线程中运行的
Thread
实现/子类),只有在
target
不是
null
时才会调用它:

现在另一个信息:如果线程完成了它的工作,它将调用将
target
设置为
null
(*)的方法:

因此,如果您在一个线程上调用了
start
,并且它已经完成了它的工作,那么您就不能再次调用
run
。。。你可以,但我不会做太多

现在让我们看一下您的代码的第一个版本:

t1.start(); -> starts a thread; takes at least 2 seconds to finish
t2.start(); -> starts a thread; takes at least 1 second to finish

t1.run(); -> blocks main thread; takes at least 2 seconds to finish
t2.run(); -> called after `t1.run()` finished;
如您所见,
t2.run()
将在
t2.start()
之后至少运行2秒,因为
t1.run()
会阻止方法调用。因此
t2
(从
t2.start()
)已完成并将
target
设置为
null
So
t2.run()
使
目标失败!=空
检查并执行“无”

现在是第二个版本:

t1.start(); -> starts a thread; takes at least 2 seconds to finish
t2.start(); -> starts a thread; takes at least 1 second to finish

t2.run(); -> blocks main thread; takes at least 1 seconds to finish
t1.run(); -> called after `t2.run()` finished;
这里
t2.run()
可以在
t2
之前运行
t2.start()
可以完成他的“睡眠”,因此
target
仍然设置正确。
t1.run()
也没有问题,因为它直接调用
ThreadImpl
的重写
run
方法,所以不需要通过检查。无论如何,通过它也不会有问题,因为
t2.run()
睡眠1秒,所以
t1.start()
中的
t1
仍然睡眠1秒,他的
目标也仍然设置。
这就是您获得“完整”输出的原因

我希望我的解释清楚,并且您理解不同输出的原因:)


(*)请注意,这种行为在其他Java环境中有所不同。但是Oracles版本和OpenJDK正在这样做。

在您的代码中,您在哪里打印过
taskinpl run()
?我看不到这一点。这里@TimBiegeleisen:
class ThreadImpl扩展了Thread{@Override public void run(){try{Thread.sleep(2000);**System.out.println(“ThreadImpl run()”);**
为什么要直接调用
Thread.run()
?发生这种情况是因为
t1.run()
t2.start();
花费的时间更多。检查
目标
是否为
null
(请参阅该类的源代码),以及线程是否已完成其工作并“退出”。因此调用
t2.run();
未能通过
目标!=null
检查。对不起,我没有时间写答案:)。@Tom这听起来很划算。基本上,他对每个线程的
run()
方法生成了两个调用。一个是异步和间接的(
start()
),另一个是同步和直接的(
run()
)。您可能希望在线程退出时将
target
设置为null是一个实现细节,可能会在JVM实现中有所不同。还有另一个原因是
t1.run()
没有问题。您演示了
thread\run()
在线程启动后不执行任何操作,并允许运行到完成;但是
t1.run()
从不调用
thread#run()
。它调用OP的
ThreadImpl#run()
方法,该方法没有相同的限制。@jameslarge,这是正确的。't1.run()'直接调用被重写的方法,而't2.run()'调用“原始”版本。感谢所有人,尤其是汤姆。@Slipknot不客气。如果这有助于您解决问题,请不要忘记。
t1.start(); -> starts a thread; takes at least 2 seconds to finish
t2.start(); -> starts a thread; takes at least 1 second to finish

t1.run(); -> blocks main thread; takes at least 2 seconds to finish
t2.run(); -> called after `t1.run()` finished;
t1.start(); -> starts a thread; takes at least 2 seconds to finish
t2.start(); -> starts a thread; takes at least 1 second to finish

t2.run(); -> blocks main thread; takes at least 1 seconds to finish
t1.run(); -> called after `t2.run()` finished;