Java 包含线程成员的可运行对象有什么问题吗?
考虑以下对象:Java 包含线程成员的可运行对象有什么问题吗?,java,multithreading,Java,Multithreading,考虑以下对象: public class Mindblower implements Runnable { private Thread ownThread; @Override public void run() { // do all the things } public Mindblower() { ownThread = new Thread(this); ownThread.
public class Mindblower implements Runnable {
private Thread ownThread;
@Override
public void run() {
// do all the things
}
public Mindblower() {
ownThread = new Thread(this);
ownThread.start();
}
}
这行吗?线程是传递给线程的Runnable的成员这一事实是否重要?在我看来,这似乎应该奏效,但想到这一点,我的头就痛了,就像我在看克里斯托弗·诺兰的电影一样
对于奖励积分,在Runnable的构造函数中调用.start()
是否重要?它可以工作
但是一个非常糟糕的做法是将需要执行的操作与实际的线程/执行组件分离开来。将两者混合使用,您不会从使用
Runnable
中获得任何好处(除了不使用扩展槽)
在您的情况下,扩展
线程
并重写运行()
将得到相同的结果。这样做毫无意义,因为您运行的线程始终可以从线程.currentThread()
访问
此外,如果你想自动启动,你应该使用这样的东西,但这仍然是不可取的。类的用户可能希望在启动线程之前执行其他操作
public class Mindblower implements Runnable {
@Override
public void run() {
// You can access your thread at any time - you can even interrupt yourself.
Thread.currentThread().interrupt();
}
public Mindblower() {
// Do not start here.
}
{
// A more acceptable way of having a self-starting thread but still not a good idea.
new Thread(this).start();
}
}
是的,它是有效的,但是您可能需要考虑其他一些方法来实现这一点,使您的代码更容易理解。您可以创建第二个
Runnable
类以从主类调用,例如:
public class Mindblower {
public static void main(String[] args) {
Thread ownThread = new Thread(new MindblowingRunnable());
ownThread.start();
// Other stuff that you want done concurrently on the main thread
}
private class MindblowingRunnable implements Runnable {
@Override
public void run() {
// Stuff to be carried out in your thread
}
}
}
如果Runnable
仅在该上下文中使用,只要Runnable
类不需要是公共的,那么这可以变得简单一些:
public class Mindblower {
public static void main(String[] args) {
Thread ownThread = new MindblowingThread();
ownThread.start();
// Other stuff that you want done concurrently on the main thread
}
private class MindblowingThread extends Thread {
@Override
public void run() {
// Stuff to be carried out in your thread
}
}
}
虽然可以保留对线程的本地引用,但这仅在需要从主线程中断线程时才有用。在Runnable
中,只需调用Thread.currentThread()
对于您的额外问题,不需要从构造函数调用start()
,甚至不需要从main()
调用。如果希望线程在程序启动后立即运行,则这两个选项都是可选的,但在某些情况下,您可能更希望先等待用户输入,然后从其他方法调用start()
所有这些都假设您只创建一个线程,或者如果有多个线程,那么它们之间的同步对您的程序来说不是问题。如果同步问题很重要,请考虑A。而不是思考这么难,为什么不运行它,看看会发生什么?线程化!不,但它应该有用。。。我认为O.O.关于构造函数的
start()
:这是一个bug!它可能导致多线程问题。当这个
从构造函数转义到另一个线程时,许多并发保证(例如最终
字段的可见性)就消失了。在您的例子中,此
被传递给构造函数中的线程
对象,然后启动该线程
对象,使它从另一个线程访问this.run
——这构成了this
从this
的构造函数中泄漏到另一个线程。这或多或少是我在寻找的,所以如果您将其作为答案提交,我将接受它。@RohitJain+1如果这不是关于多线程的。不幸的是,它是。我同意,它似乎不是一个好主意,可能不是我会做的事情。我关心的是,这是否会机械地导致问题(一些疯狂的递归堆栈溢出或类似的事情)。没有递归的东西。这或多或少是我的处理方法。OP中的问题是一对what-if,这个答案解决了这两个问题。谢谢