How to understand this detailed multithreading and anonymous class related code? - java

public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
System.out.println("hello");
}
})
{
public void run() {
System.out.println("world");
}
}.start();
}
Simply I get "world" with this. Why it can be written in this manner? What is the first run() method for?

This (contrived) code passes an instance of an anonymous Runnable class to an instance of an anonymous Thread class that overrides its usual implementation of run().
It's becomes (a little) clearer if you refactor it:
// The runnable instance
Runnable runnable = new Runnable() {
public void run() {
System.out.println("hello");
}
};
// Anonymous Thread class with a custom run() method
new Thread(runnable) {
public void run() {
System.out.println("world");
}
}.start();
The Runnable passed to the Thread, which would be executed by the thread's start() method, is ignored because the Thread object is also an instance of an anonymous class with a custom implementation of its run() method, which is hard-coded to print "world".

This code creates an instance of an anonymous sub-class of Thread and then starts that thread.
That sub-class overrides Thread's run() method with a method that prints "world".
The first run() method is part of an anonymous implementation of the Runnable interface which is passed to the constructor of the Thread instance. That implementation is ignored, since your Thread implementation overrides run().
The Runnable instance passed to the thread constructor is only executed (when the thread starts) if the Thread's run() method is not overridden.

The Thread class defines run() in this way :
#Override
public void run() {
if (target != null) {
target.run();
}
}
It invokes the run() method of the Runnable instance (target field of Thread)if this field is not null.
So when you create an anonymous class of Thread that overrides this method in this way:
new Thread(...) {
#Override
public void run() {
System.out.println("world");
}
}
The Thread run() method of the anonymous instance doesn't rely any longer on the target field to run the Runnable instance.
It execute only this code :
System.out.println("world");
So the Runnable instance passed to the constructor of Thread is totally ignored by run():
new Runnable() {
public void run() {
System.out.println("hello");
}
}

You have overridden the run method which prints hello with the one which prints world. This happened because in your code you have extended the Thread class with an anonymous class which overrode the run method, therefore the Runnable parameter's run is never called. You can update the code to use super.run() to call the runnable method from the original class.
Here is your code with the changes:
new Thread(new Runnable() {
public void run() {
System.out.println("hello");
}
}) {
public void run() {
super.run();
System.out.println("world");
}
}.start();

Related

showing error while im trying to override the run method

package com.jspiders.thread;
public class Mthrd1 extends Thread {
{
#Override
//error line public void run()
{
// TODO Auto-generated method stub
super.run();
}
}
}
This is a valid way to override the run method for creating threads:
class Test extends Thread
{
public void run()
{
System.out.println("Thread Started and is Running");
}
public static void main(String args[])
{
Test t=new Test();
t.start();
}
}
There is also another way to create threads in java by implementing the runnable interface. In you posted code you are calling the run method explicitly whereas, for calling the run method of Thread class you need to call start() method which implicitly calls the run method of Thread, your program is showing error because as you are calling run method explicitly and in your class you have no method called run.

Getting the method that creates runnable from thread which runs the runnable

Suppose I have a custom Thread class which is responsible for running runnables
public class MyThread extends Thread{
public MyThread(Runnable r) {
super(r);
}
#Override
public void run() {
super.run(); // Can I put something here to get info about where the runnable is submitted from?
}
}
Then in some method, I submit the runnable
public void someMethod() {
new MyThread(new Runnable() {
#Override
public void run() {
System.out.println("Blah");
}
});
}
Suppose I have no control over someMethod, can I modify MyThread such that whenever a runnable is submitted to MyThread, I can get info about someMethod (e.g. method name someMethod, class name) ?
Edit
In fact the original question is part of my problem.
I am providing a ThreadFactory that can be used by a threadpool (ExecutorService).
public class MyThreadFactory implements ThreadFactory {
#Override
public Thread newThread(Runnable r) {
return new MyThread(r);
}
}
User can create a threadpool with MyThreadFactory
ExecutorService pool = Executors.newCachedThreadPool(new MyThreadFactory());
By calling pool.execute(runnable), a instance of MyThread will be created to perform the task specified by runnable. It is possible that the thread will be reused by multiple runnables. So I would like to retrieve Method and Class info in the public void run() method of MyThread. Since runnable is stored in a private field in the base Thread class, I cannot use a modified version of the solution provided by Laerte like:
#Override
public void run() {
super.run();
// Not working, Since MyThread cannot access private field target of Thread class
Method m = target.getClass().getEnclosingMethod();
System.out.println(m.toString());
}
Can I still obtain Method and Class about where the runnable is instantiated , at the moment public void run() is invoked?
To know things related to calling methods, class names, and so on, you should use reflection.
In your case, you should modify your code like this.
class MyThread extends Thread{
public MyThread(Runnable r) {
super(r);
Method m = r.getClass().getEnclosingMethod();
System.out.println(m.toString());
}
#Override
public void run() {
super.run();
}
}
The Method class will have the method reference. Using this call Method m = r.getClass().getEnclosingMethod();, you will receive the method that is enclosing the Runnable object. In your case, oneMethod.
That's the idea. Tell me if it helps.

Callback from new thread to class from which thread was initiated

I have a class from which I am calling a new thread.
public class MainClass{
private void cleardata() {
// do something on a separate thread
new Thread(new Runnable() {
#Override
public void run() {
//Do Something
//After this I would like to notify my MainClass that some thing has been done and pass a value.
}
}
}
private void callbackFunc(int a){
// Do something based on value of a
}
}
I have a function in my MainClass. But how do i call this function from my new thread, so as to receive a callback.
Thanks.
You should just be able to call the method in MainClass by its name just as if you were calling from directly inside MainClass itself (as opposed to from the inner class).
If a method name you want to call happens to conflict with one that your inner class has inherited from Object then you can prefix the call with MainClass.this, e.g. MainClass.this.toString() calls toString on MainClass, whereas just toString() calls it on the inner class instance.
In such a case pass the instance of MainClass to the thread class ((during creation)) so that it can call method on it. Having inner class as suggested by others is also a good option.
Something similar-
class MainClass {
private void cleardata() {
new Thread(new MyThread(this)).start();
}
}
class MyThread implements Runnable {
private MainClass mc;
MyThread(MainClass mc) {
this.mc = mc;
}
public void run() {
// do something
// mc.someMethod();
}
}
public class MainClass{
private void cleardata() {
// do something on a separate thread
new Thread(new Runnable() {
#Override
public void run() {
callBackFunc(result);
}
}
}
private void callBackFunc(int a) {
}
}
Just do it:
public class MainClass{
private void cleardata() {
// do something on a separate thread
new Thread(new Runnable() {
#Override
public void run() {
//Do Something
notifyTheClass("a parameter");
}
}
private void notifyTheClass(String aParam) {
//..do something else
}
}
}
But it is not related to threads, this is about inner classes. If you want the main thread to wait until the new thread is finishes, use Futures for a result. Or use some other multithreading primitives.

Thread: Not calling run method

I am new in java. Can someone help me why it is not calling Run method.
Thanks in advance.
package com.blt;
public class ThreadExample implements Runnable {
public static void main(String args[])
{
System.out.println("A");
Thread T=new Thread();
System.out.println("B");
T.setName("Hello");
System.out.println("C");
T.start();
System.out.println("D");
}
public void run()
{
System.out.println("Inside run");
}
}
You need to pass an instance of ThreadExample to the Thread constructor, to tell the new thread what to run:
Thread t = new Thread(new ThreadExample());
t.start();
(It's unfortunate that the Thread class has been poorly designed in various ways. It would be more helpful if it didn't have a run() method itself, but did force you to pass a Runnable into the constructor. Then you'd have found the problem at compile-time.)
The run method is called by the JVM for you when a Thread is started. The default implementation simply does nothing. Your variable T is a normal Thread, without a Runnable 'target', so its run method is never called. You could either provide an instance of ThreadExample to the constructor of Thread or have ThreadExample extend Thread:
new ThreadExample().start();
// or
new Thread(new ThreadExample()).start();
You can also do it this way.Do not implement Runnable in your main class, but create an inner class within your main class to do so:
class TestRunnable implements Runnable{
public void run(){
System.out.println("Thread started");
}
}
Instantiate it from your Main class inside the main method:
TestRunnable test = new TestRunnable();
Thread thread = new Thread(test);
thread.start();

Why does a java.lang.Thread not call the run() method of its explicit java.lang.Runnable when started?

The Java docs state that if we supplied a Runnable target when creating a new thread, .start() of that thread would run the run() method of the supplied runnable.
If that's the case, shouldn't this test code prints "a" (instead of printing "b") ?
public class test {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
System.out.println("a");
}
};
Thread t = new Thread(r) {
#Override
public void run() {
System.out.println("b");
}
};
t.start();
}
}
Because you are overriding Thread.run() method.
Here is the implementation of Thread.run():
#Override
public void run() {
if (target != null) {
target.run();
}
}
try:
}) {
#Override
public void run() {
super.run(); // ADD THIS LINE
System.out.println("b");
}
}.start();
You will get ab.
The default implementation is to call the Runnable. However you are overriding the default implementation and NOT calling the runnable. The simplest way to fix this is
new Thread(new Runnable() {
#Override
public void run() {
System.out.println("a");
}
}) {
#Override
public void run() {
super.run(); // call the default implementation.
System.out.println("b");
}
}.start();
The default implementation of Thread.run() does what the javadocs say (look at the source code)
public void run() {
if (target != null) {
target.run();
}
}
However, Thread.run() is public, and you overrode it, so it calls your println("b"), and totally ignores the Runnable passed in the constructor. Arguably, Thread.run() should be final, but it isn't.
You have overridden the default implementation of Thread.run() in what I guess is an anonymous subclass, hence what the JavaDoc says no longer applies.
If you try
public class Test {
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
System.out.println("a");
}
}) .start();
}
}
You get the answer you expect, a.
The first block overrides run in Runnable. The second block overrides run in Thread. When you call start on a Thread, its run method is invoked. The default run method in Thread calls the Runnable.run method but since you overrode Thread.run there is no code to start the Runnable - only your code to print 'b'.
The documentation that I have says this:
"Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread."
which means that it should print b instead of a, since you have overridden the run() method of Thread.
You are calling start() method. Reading the docs in the link you provided it states:
public void start()
Causes this thread to begin execution; the Java
Virtual Machine calls the run method of this thread.
You should call the run() method if you would like to call the Runnable object's run method.
public void run() If this thread was constructed using a separate
Runnable run object, then that Runnable object's run method is called;
otherwise, this method does nothing and returns.
You are actually extending the Thread class and calling start on the instance of that anonymous subclass.
I think the confusion is that the "Java Doc" is for the java.lang.Thread class not for your class that extends that class.
e.g.
Runnable r = new Runnable() {
#Override
public void run() {
System.out.println("a");
}
};
Thread t = new Thread(r);
Now, if it does not call that run then java doc is wrong. Which is not true.

Categories