我正在尝试理解Java中的Threads。我创建了一个实现Runnable
接口的线程,该接口执行某个类的某个功能。以下是Java类:
MyThread Class
public class MyThread implements Runnable {
private DataContainer dataContainer;
private Thread thread;
public MyThread(DataContainer dataContainer) {
this.dataContainer = dataContainer;
thread = new Thread(this);
thread.start();
thread.setName("Thread 2");
}
@Override
public void run() {
System.out.println("MyThread : "+dataContainer.toString());
}
public void runThread() {
thread.run();
}
}
DataContainer Class
。我在线程中执行的功能
public class DataContainer {
private static DataContainer instance = null;
private DataContainer() {}
public static DataContainer getInstance() {
if(null == instance)
instance = new DataContainer();
return instance;
}
@Override
public String toString() {
return Thread.currentThread().getName()+" : __Data__";
}
}
main class
public class Launcher {
public static void main(String[] args) {
DataContainer dataContainer = DataContainer.getInstance();
MyThread myThread = new MyThread(dataContainer);
int i =0;
while(i++<10) {
System.out.println("Launcher : "+ dataContainer.toString());
myThread.runThread();
}
}
}
问题是,在while
循环中,从主类和myThread实例执行dataContainer.toString(),我得到输出,因为它们都在一个线程中运行:{{1} }。循环中的所有执行都不是从main thread
执行的。
我的目标是,Thread 2
在线程in the while loop, I want myThread.runThread()
下执行。
修改
添加了Thread 2
。
但是,现在只执行一次?每次我想执行myThread.runThread()时都无法创建新线程。通过在循环中创建一个新线程,我最终会创建一堆线程。这是可取的吗?我想要一个代码(比如Y)由一个线程(比如说X)执行。每次Y必须执行时,都应该通过线程X来完成。
解决方案
这可能是一个可能的解决方案:
thread.start()
答案 0 :(得分:3)
thread.run();
只是在当前线程的上下文中直接调用Runnable
s run
方法。如果您只是在run()
方法中调用runThread
,则会得到相同的结果。
您需要致电thread.start()
,这将创建一个新的流程线程并最终调用您的Runnable
run
方法
您应该创建Thread
并在需要时将Runnable
设置为Thread
,而不是将Runnable
换成public class MyThread implements Runnable {
private DataContainer dataContainer;
public MyThread(DataContainer dataContainer) {
this.dataContainer = dataContainer;
}
@Override
public void run() {
System.out.println("MyThread : "+dataContainer.toString());
}
}
,这是违反直觉且通常设计不合理的问题。 ,例如......
DataContainer dataContainer = DataContainer.getInstance();
MyThread myThread = new MyThread(dataContainer);
Thread thread = new Thread(myThread );
thread.setName("Thread 2");
thread.start();
System.out.println("Launcher : " + dataContainer.toString());
然后你可以做一些像......
{{1}}
答案 1 :(得分:1)
myThread.runThread()
将在当前线程中调用该方法。如果您希望在新线程中执行该操作,请将该调用置于run
方法中,然后只需调用myThread.start()
。这将启动另一个线程,并调用runnable对象的run方法。
答案 2 :(得分:1)
定义实现Runnable的类时,不需要包含Thread对象。
简单地
class myThread implements Runnable {
@Override
public void run() {
// do something
}
}
new Thread (new myThread ()).start ();
答案 3 :(得分:0)
我没有尝试理解你的例子(过于复杂),但这是个坏主意:
public class Foobar implements Runnable {
private XType x;
private YType y;
private Thread thread;
public Foobar() {
x = new XType();
thread = new Thread(this); //Not in a constructor!!!
thread.start();
y = new YType();
}
@Override
public void run() {
doSomethingWith(y); // y can be uninitialized at this point.
doSomethingElseWith(x); // x can be uninitialized too!!!
}
}
这个反模式有一个名称,它被称为&#34;从构造函数中泄漏this
。&#34; Foobar构造函数启动新线程,并在新对象完全初始化之前为其提供对新Foobar实例(即this
)的引用。当以这种方式发布对象时,Java语言规范不保证对象对新线程的外观。 (Google for&#34; safe publication&#34;)
特别是,当首次输入run()方法时,任何对象的成员变量(包括x !!)都可能从新线程的角度看似未初始化。 / p>
最佳实践:不要在构造函数或构造函数调用的任何帮助方法中使用this
,并且还要将帮助器声明为final
,以便class不能覆盖一个并以这种方式查看未初始化的对象。
class Foobar {
Foobar(...) {
...don't use "this" here...
fooHelper(...);
}
private final void fooHelper(...) {
...don't use "this" here either...
}
}