How can I get the variable with the value from Thread Run method?
We want to access a variable from the run method of a Thread externally in a class or in a method. Even though I make the variable as public /public static, I could get the value till the end of the run method only. After that scope of the variable gets lost resulting to null value in the called method/class..
How can I get the variable with the value?
This is sample code:
public class SampleSynchronisation
{
public static void main(String df[])
{
sampleThread sathr= new sampleThread();
sathr.start();
System.out.println("This is the value from the run method "+sathr.x);
// I should get Inside the run method::: But I get only Inside
}
}
class sampleThread extends Thread
{
public String x="Inside";
public void run()
{
x+="the run method";
}
}
NB: if i write the variable in to a file I am able to read it from external method. This I dont want to do
[1027 byte] By [
planswerme] at [2007-9-26 3:35:32]

Well, where should I start. Normally this would be a thread-unsafe case, since sampleThread is manipulating it's x variable, while SampleSynchro is reading it. Since you don't seem to have synchronized anywhere this can result in corrupt data etc.
Try adding a Thread.sleep(10); after sathr.start(). I don't know if it'll help, probably not. But your whole program is odd. It's trying to catch the String "Inside the run method" from the other thread. Why don't you add in the run method a while loop or something to keep the thread alive, that way you don't have to code like a surgeon.
Ok this would make it worksathr.start();sathr.run(); // <--add this after the start()
Hi! I'd recommend changing your design. Here's what I mean. Use a data object that's passed to the thread constructor. Modify the data object within the thread. Now you can access the data object outside the thread. However, it's a very good idea to ensure that the thread has finished manipulating the data object prior to accessing it from some other place.
public class MyData
{
// Define the data class
public void foo()
{
// Do something
} // foo
} // class MyData
public class MyThread extends Thread
{
private MyData m_data;
public MyThread( MyData data )
{
m_data = data;
} // constructor
public void run()
{
// Do something here with m_data
} // run
} // class MyThread
public class MyDriver
{
public static void main( String[] cmdArgs )
{
MyData data = new MyData();
MyThread mt = new MyThread( data );
mt.start();
// You can access the data object here. Ensure that
// proper synchronization is in place before doing so.
} // main
} // class MyDriver
Hope this helps! Feel free to ask if something's not too clear.
Cheers!
amolk at 2007-6-29 12:06:02 >

> We want to access a variable from the run method of a
> Thread externally in a class or in a method.
I presume you mean a member variable of the thread class and not a local variable inside the run() method.
> Even
> though I make the variable as public /public static, I
> could get the value till the end of the run method
> only. After that scope of the variable gets lost
> resulting to null value in the called method/class..
>
I find it easier to implement the Runnable interface rather than extending a thread. This allows your class to extend another class (ie if you extend thread you can't extend something else, but if you implement Runnable you have the ability to inherit from something). Here's how I would write it:
public class SampleSynchronisation
{
public static void main(String[] args)
{
SampleSynchronisation app = new SampleSynchronisation();
}
public SampleSynchronisation()
{
MyRunnable runner = new MyRunnable();
new Thread(runner).start();
// yield this thread so other thread gets a chance to start
Thread.yield();
System.out.println("runner's X = " + runner.getX());
}
class MyRunnable implements Runnable
{
String X = null;
// this method called from the controlling thread
public synchronized String getX()
{
return X;
}
public void run()
{
System.out.println("Inside MyRunnable");
X = "MyRunnable's data";
}
} // end class MyRunnable
} // end class SampleSynchronisation
>
> public class SampleSynchronisation
> {
> public static void main(String df[])
> {
> sampleThread sathr= new sampleThread();
> sathr.start();
> System.out.println("This is the value from the run
> method "+sathr.x);
> // I should get Inside the run method::: But I get
> only Inside
> }
> }
>
>
> class sampleThread extends Thread
> {
> public String x="Inside";
> public void run()
> {
> x+="the run method";
> }
>
> }
>
>
> NB: if i write the variable in to a file I am able to
> read it from external method. This I dont want to do
The output you are getting is pretty much what I'd expect from your code. If you run the example many times though, you'll finid that occaisonally you get the output you were expecting.
When you call start on your simpleThread object, that puts the thread in a state such that it will run next time it is allocated a time-slice by the processor. When you print the value out, it is the next statement after calling start, so its quite likely that the thread that called start is still running, and that the thread you started hasn't actually begun its run method yet.
Threads do not run con-currently - they get small time-slices and to the user it appears that they are all running at the same time.
If you call Thread.sleep after calling start in your main method, then the simpleThread object will probably begin to execute its run method and by the time the main thread wakes up again, the value of the variable will have changed.
> Threads do not run con-currently - they get small
> time-slices and to the user it appears that they are
> all running at the same time.
Java threads do not get time-slices actually. In Windows they do because you end up using native threads (actually I prefer time-slicing, so don't get me wrong, it makes life easier sometimes). In Solaris, you will not see time-slicing when using green threads.
A Java thread will run to completion before it lets another thread of the same priority even get a chance to run. By calling "yield()" or "sleep()" you are giving another thread of the same priority a chance to run. So I partially agree with you.
I was going to suggest yield as a way to get the behaviour, but isn't it actually still up to the operating sytem what it does - if you call yield you don't guarantee that another thread will take control since the operating system gets to choose (and it could well choose the thread that just caused yield).
I don't know all the details when it comes to multithreading - just an understanding of the basics.
Do you not always use native threads? - If not, do you know why its only a WIndows thing?
You are correct, as I said (and as far as I know), yield() only gives the OS a chance to choose a thread to run, it does not guarantee that a different thread will be chosen. Presumably, the OS is smart enough to "time-share" the threads based on yields and sleeps.
> Do you not always use native threads? - If not, do you
> know why its only a WIndows thing?
My guess is that a green thread implementation of a JVM in Windows would give horrible performance. It makes sense to let the OS handle the threading in a lot of cases. I'm not sure about Solaris green/native thread running, but the following code :
public class ThreadTester
{
public static void main(String[] args)
{
new Thread(new MyRunner("One")).start();
new Thread(new MyRunner("Two")).start();
}
class MyRunner implements Runnable
{
String name = "noname";
public MyRunner(String _name)
{ name = _name; }
public void run()
{
for(int loop = 0; loop < 10000; loop++)
System.out.println("In MyRunner " + name);
}
} // end class MyRunner
} // end class ThreadTester
Will run very differently on Windows and Solaris boxes.
To make them run in a similar fashion, it's necessary to call Thread.yield() or sleep() in the for loop in the run() method.
I think the important point to make about multithreading is that you can never be certain your code will execute the same from run to run, unless you're coding for a particular JRE on a Particular OS (and that includes different versions of the same OS), and the JRE you're using makes guarantees about how threads will be handled on that particular OS.
Ok first off the guy who said add sathr.run(); after the start method must be kidding. If your not you really need to do some reading about threads. I'm not being mean just honest.
One big issue nobody has brought up yet is cpu caching. If your second thread, the one you start gets started on a seperate cpu then the assignment via += may NEVER be seen by any other thread. The reason is because the write will most likely happen to the local cpu's cache and not main memory. One way of fixing this is to use object locks. I would really suggest doing the following even if you are not running on a multi-cpu machine.
1. Use locks if you can, when you enter synchronized code you are guaranteed to reload cached data from main memory. When you leave synchronized code you flush from cache to main memory. You could change x to an Integer and use that as your lock.
2. Mark x volatile.
3. Maybe read Doug Lea's book on multithreading. He can explain this stuff a lot better than me. :)
hope this helps.
It sounds like you want a callback of some kind to tell you when the run method of your thread has finished running. OR am I wrong?You really can't depend on the other thread being executed at all. ( It will be but you have no control as to when )
It sounds like you want a callback of some kind to tell you when the run method of your thread has finished running. OR am I wrong?You really can't depend on the other thread being executed at all. ( It will be but you have no control as to when )
put sathr.join(); after starting the thread.
Actually by this what will happen is main thread will wait till the child thread sathr completes its execution. So there by when you print after this statement. value of x as in run method will be printed.
Thanks,
Vijay
cvij at 2007-6-29 12:06:02 >
