Unable to access global variables via Runnable in class - java

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;

Related

Thread safe access to private field

So I have the following scenario (can't share the actual code, but it would be something like this):
public class Test
{
private Object obj;
public void init()
{
service.registerListener(new InnerTest());
}
public void readObj()
{
// read obj here
}
private class InnerTest implements Listener
{
public synchronized void updateObj()
{
Test.this.obj = new Object();
// change the obj
}
}
}
The InnerTest class is registered as listener in a service. That Service is running in one thread the calls to readObj() are made from a different thread, hence my question, to ensure consistency of the obj is it enough to make the UpdateObj() method synchronized?
I would suggest using another object as a lock to ensure that the class only blocks when the obj is accessed:
public class Test
{
private final Object lock = new Object();
private Object obj;
public void init()
{
service.registerListener(new InnerTest());
}
public void readObj()
{
synchronized(lock){
// read obj here
}
}
private class InnerTest implements Listener
{
public void updateObj()
{
synchronized(Test.this.lock){
Test.this.obj = new Object();
// change the obj
}
}
}
}
Then use that lock in all methods that need to have consistent access to obj. In your current example the readObj and updateObj methods.
Also as stated in the comments, using synchronized on the method level in your InnerTest class, will not really work as you probably intended. That is, because synchronized methods will use a synchronized block on the this variable. Which just blocks your InnerTest class. But not the outer Test class.

How to share a variable between two sub classes that implements runnable

I have a main class and two subclasses, subClass1 and subClass2 that implements runnable...
I have run the two threads simultaneously
by calling
t1.start // t1 for subclass1
t2.start // t2 for subclass2
Now, I want t1 to run till the t2 completes.
I can add a boolean flag within the method in subclass2 to recognize that the execution has been completed;
Now I need to pass that information(boolean variable) to subclass1 to stop the execution of a set of codes from within it. [have used while(true) loop;]
so how can i create a common variable that can be accessed by both sub classes?
Can anybody please suggest me a solution for this?
Pass an AtomicBoolean to the subclasses.
public class SubClass1 implements Runnable {
private AtomicBoolean b;
public SubClass1(AtomicBoolean b) {
this.b = b;
}
public void run() {
while(b.get()) { // Assuming SubClass2 sets it to false when it's no longer running
// Do something
}
}
}
Implementing SubClass2 is left as an exercise to the OP.
If possible I'd recommend to avoid sharing mutable state in concurrent environment, but assuming you have one of those cases where it cannot be avoided you can try something like (adjust for your own needs):
class SharedState {
public final Object mutex = new Object();
public boolean variable;
}
class Subclass extends MyClass1 implements Runnable {
private SharedState sharedState;
public Subclass1(SharedState sharedState) {
this.sharedState = sharedState;
}
// ...
#Override
public void run() {
// ...
synchronized(sharedState.mutex) {
// access sharedState.variable
}
// ...
}
}
Basically create SharedState outside and inject into your subclasses on creation (or create it within one of them, retrieve and inject into another, whatever). Then use that shared variable remembering all you know about trickiness of shared state.

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.

Inner class runnable in java

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.

How to pass an argument to a thread [duplicate]

This question already has answers here:
How can I pass a parameter to a Java Thread?
(19 answers)
Closed 9 years ago.
Assume I would like to pass the following variable
String foo = "hello world";
as an argument to the following thread
new Thread(new Runnable() {
#Override
public void run() {
// SOME CODE HERE REQUIRES VARIABLE
}
}).start();
Can someone please explain how to do this.
Thanks.
Subclass Thread:
public class MyThread extends Thread {
private String arg;
public MyThread(String arg) {
this.arg = arg;
}
#Override
public void run() {
// Use your variable
}
}
Local variables that are declared as final will be visible in the thread:
void doSomething(final String foo) {
new Thread(new Runnable() {
#Override
public void run() {
// SOME CODE HERE REQUIRES VARIABLE
System.out.println(foo);
}
}).start();
}
Can someone please explain how to do this.
So your problem has more solutions but nicely from the beginning. I suggest you to create own subclass of Thread and pass parameter via its constructor.
public class MyThread extends Thread {
public MyThread(String value) {
}
}
Or you can also use Runnable interface as well.
public class MyThread implements Runnable { ... }
Update:
Or like #erickson pointed out you can wrap your code into body of method but as method's argument you have to pass final variable because you cannot cannot refer to a non-final variable inside inner class defined in a different method.
You can't pass argument using anonymous classes in Java. What you can do is create a separate class and pass it as instance variable
String foo = "hello world";
final String parameter = foo;
new Thread(new Runnable() {
#Override
public void run() {
//Use parameter
}
}).start();

Categories