I'm trying to understand Threads in Java. I've created a thread implementing the Runnable
interface, which executes a certain function of a certain class. The following are the Java classes:
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();
}
}
The DataContainer Class
. The function of which I execute in the thread
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__";
}
}
The 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();
}
}
}
The problem is, in the while
loop where is execute the dataContainer.toString() from the main class and the myThread instance, I get the output as they are all running in one thread: main thread
. None of the executions in the loop are executed from Thread 2
.
My aim is that, in the while loop, I want myThread.runThread()
to be executed under the thread Thread 2
.
EDIT:
Added thread.start()
. However, now it gets executed only once? I can't create a new thread every time I want to execute myThread.runThread(). By creating a new thread in the loop, I'd end up creating a bunch of threads. Is this advisable? I want a certain piece of code(say Y) to be executed by a thread(say X). Every time Y has to be executed, it should be done through the thread X.
Solution
This can be a possible solution:
public class MyThread implements Runnable {
private DataContainer dataContainer;
private Thread thread = null;
public MyThread(DataContainer dataContainer) {
this.dataContainer = dataContainer;
}
@Override
public void run() {
System.out.println("MyThread : "+dataContainer.toString());
}
public void runThread() {
boolean threadIsAlive = (null!=thread && Thread.getAllStackTraces().keySet().contains(thread));
if(null == thread || !threadIsAlive) {
thread = new Thread(this);
thread.start();
} else {
thread.run();
}
}
}
thread.run();
is just calling your Runnable
s run
method directly, within the current thread's context. You'll get the same result if you're simply called run()
in you runThread
method.
You need to call thread.start()
, this will create a new process thread and eventually call your Runnable
s run
method
Rather than wrapping a Thread
instead a Runnable
, which is counterintuitive and generally bad design, you should create Thread
and set the Runnable
to it when you need to, for example...
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());
}
}
Then you could do something like...
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());
myThread.runThread()
will just invoke that method in current thread. If you want that to be executed in new thread, put that call in run
method and just call myThread.start()
. This starts another thread and calls run method of your runnable object.
When you define a class which implements Runnable, you do not need to have a Thread object in it.
Simplistically
class myThread implements Runnable {
@Override
public void run() {
// do something
}
}
new Thread (new myThread ()).start ();
I didn't try to understand your example (too convoluted), but this is a bad idea:
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!!!
}
}
This anti-pattern has a name, It's called "leaking this
from a constructor." The Foobar constructor starts the new thread, and gives it a reference to the new Foobar instance (ie, this
) before the new object has been fully initialized. The Java language spec makes no guarantees about what the object will look like to the new thread when the object is published in this manner. (Google for "safe publication")
In particular, When the run() method is first entered, any of the object's member variables (including x!!) can appear to be uninitialized from the new thread's point of view.
Best Practice: Don't ever use this
in a constructor or in any helper method that is called by the constructor, and also, declare helpers to be final
so that a sub-class can't override one and see the un-initialized object that way.
class Foobar {
Foobar(...) {
...don't use "this" here...
fooHelper(...);
}
private final void fooHelper(...) {
...don't use "this" here either...
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.