say I have a class called "Example"
inside "Example" I have an inner class which is a runnable
I execute the runnable inside "Example"
public class Example {
public Example() {
//executing the runnable here
}
private void a() {
}
public void b() {
}
public class RunMe implements Runnable {
public void run() {
a();
b();
}
}
}
what happens here assuming that Example runs on the main thread?
does a and b run from the RunMe thread or the main thread?
does it matter that a is private and b is public?
You missed out the key piece of code to enable us to answer your question - the constructor.
If your constructor looks like this:
public Example() {
(new Thread(new RunMe())).start();
}
Then a() and b() will run on the thread you just created (the "RunMe" thread as you call it).
However, if your constructor looks like this:
public Example() {
(new RunMe()).run();
}
Then you're not actually running it on another thread (you're just calling a method in another class, it just happens to be called 'run'), and so a() and b() will run on the 'main' thread.
The private/public thing is irrelevant here because RunMe is an inner class so can access even private methods of Example.
If your Example constructor has in it
new Thread(new RunMe()).start()
then a() and b() will run on that thread.
However, they may run before the constructor has finished executing, so their behaviour will be undefined.
Inner class are just some magic kind of extracted/transformed.
public static class Example$RunMe implements Runnable {
// Autocode
private final Example $this;
public RunMe(Example _this){
$this=_this;
}
public void run() {
$this.a(); // even if private
$this.b();
}
}
So the thread you are calling run is the Thread a() and b() are called, it makes no difference if they are public or private.
Related
I have a method that I want to call in RunnerClass, in a non-static way in ThreadClass.
public class CallingClass{
CallingClass(){
ClassTwo thread = new ClassTwo();
thread.start();
}
public void someMethod(){}
}
public class ThreadClass extends Thread{
public void run(){
//Some thread logic
CallingClass.someMethod();
}
}
Obviously this won't work. The method is not static (and I'm not allowed to make it static), but in the above example I'm trying to access it in a static way, if only because I feel it best represents what I would like to do.
If it makes sense, I would like for the thread to be able to notify the instance of CallingClass that it needs to call someMethod()
Is there a neat way to do this?
What about creating ClassTwo constructer that gets a parameter with CallingClass type?
public class ThreadClass extends Thread{
CallingClass callingClass;
public ThreadClass(CallingClass callingClass) {
this.callingClass = callingClass;
}
public void run(){
//Some thread logic
callingClass.someMethod();
}
}
And create ClassTwo like this:
public class CallingClass{
CallingClass(){
ClassTwo thread = new ClassTwo(this);
thread.start();
}
public void someMethod(){}
}
You could use ThreadClass as an inner class of CallingClass and call the mothod directly.
public class CallingClass{
CallingClass(){
ClassTwo thread = new ClassTwo();
thread.start();
}
public void someMethod(){}
public class ThreadClass extends Thread{
public void run(){
//Some thread logic
someMethod();
}
}
}
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();
I wonder if the following code is OK:
public class MyClass {
...
static {
new MyClass().start();
}
private void start() {
//running the thread
}
}
I must add, I don't have access to something like main method, because this part of code is called from outside.
Does exists more sophisticated way of starting this thread?
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.
Good Day,
I have a class called FunctionHandler, that contains a method called evaluate like this:
class FunctionHandler{
Object globalVar;
public void Evaluate(){
ThreadPool pool;
Runnable task = new Runnable(){
public void run() { aWorkerTask(globalVar); }
}
pool.start(task);
pool.stop();
}
public void aWorkerTask(Object object){//worker stuff}
}
The problem is, my Runnable object can't seem to access globalVar! It seems to be it's own object somehow that can't reference what is inside it's class. Is there anyway around it?
The problem is that this code inherently doesnt work. Runnable cannot access globaVar. I need aWorkerTask to be wrapped in a Runnable and it needs access to globalVar
I'm not sure if this is the best implementation, but what I did was to create a class that implements Runnable as such:
public class MyRunnable implements Runnable {
private FunctionHandler functionHandler; //Global Reference - Only reading from it
private Object globalVar;
public MyRunnable(FunctionsHandler functionsHandler,Object globalVar) {
this.functionsHandler = functionsHandler;
this.globalVar = globalVar;
}
public void run(){
functionHandler.aWorkerTask(globalVar)
}
}
And pass in the main object functionHandler, which contains the function I need to make as a Runnable.
I then create a runnable as such:
MyRunnable taskProcessor = new MyRunnable(this,variableName,functionValues,jobNum.toString());
threadPool.runTask(taskProcessor);
A Runnable object is indeed its own object. Your options are to set it via a mutator or declare globalVar as final. Here's the mutator solution, in case you don't want globalVar to be final:
public void startRun() {
Object globalVar = new Object();
Runnable run = new Runnable() {
Object localVar;
public Runnable prepare(Object param) {
localVar = param;
return this;
}
#Override
public void run() {
/* Do your stuff */
}
}.prepare(globalVar);
}
Note that if you do this and you want globalVar to be modifiable both inside and outside the thread, you'll need to wrap it in a suitable dereferencing object.
If you want runnables to be able to access class variables, they have to be static; just change your code to:
static Object globalVar;