how can I change a boolean which I defined in the Main class from inside a Thread? It doesn't seem to work using booleanName = true;.
Is there a way to change the variable's value?
Changing the value works just like that. booleanName = false if booleanName is reachable from your thread code, or something like Main.setBooleanName(false) if it is not.
If you want to read that boolean from another thread, you also have to make sure that the new value is visible to your other thread. This can be done by making booleanName volatile, using a thread-safe boolean type like AtomicBoolean or entering/leaving a synchronized method or block before reading from booleanName.
As suggested by others, you should post your sample code. If you are asking if you can change the state of a variable from inside the run() method of a thread, yes, of course it's possible.
public class MyThread implements Runnable {
private boolean b = true;
public void run() {
b = false;
System.out.println(b);
}
public boolean getBoolean() {
return b;
}
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new MyThread());
t.start();
}
}
Related
My code basically goes like this:
//in Main Thread: (myList is a volatile field)
myList = new ArrayList<myClass>();
Thread myThread = new Thread(new MyCustomRunnable(myList));
myThread.start();
//some lines of code NOT involving myList
myThread.join();
//myList appears empty here even though I can see that the list has been populated
//in the other thread
Is there a reason for this behavior? Like I said, i can see in the debugger that the list has been populated in the called thread, but these changes don't appear in the caller thread after the join() method. MyCustomRunnable also declares the ArrayList as a volatile field, assigned by the constructor.
UPDATE:
Ok, I made a simpler program, replacing the ArrayList with a simple Integer and the results are the same...
public class Threading {
private volatile static Integer i = 0;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new MyCustomRunnable(i));
t.start();
t.join();
System.out.println(i); //prints '0', I expected '1'
}
}
public class MyCustomRunnable implements Runnable {
private volatile Integer i;
public MyCustomRunnable(Integer i) {
this.i = i;
}
public void run() {
this.i = 1;
}
}
Why isn't the Integer's value updated in the main Thread?
Add
public static void setI(int i) {
Threading.i = i;
}
to your Threading class and in your runnable add
public void run() {
this.i = 1;
Threading.setI(1);
}
This has nothing to do with multithreading, just variable scoping. i in the Threading class is not updated in MyCustomRunnable's run method.
Say I have a class with 2 instance variables and the following methods (simplified for this question):
private final Object lock = new Object();
private boolean running;
public MyClass() {
synchronized(lock) {
running = false;
}
}
public void methodA() {
synchronized(lock) {
running = true;
}
}
public void methodB() {
synchronized(lock) {
if (!running) {
return;
}
}
}
I was looking at this code, and after reading about AtomicBoolean, I thought that one might fit here, especially after looking at the MyClass constructor and methodA. I wasn't too sure about methodB though.
Assuming these methods could get called by multiple threads, would the following be thread-safe?:
private AtomicBoolean running;
public MyClass() {
running = new AtomicBoolean(false);
}
public void methodA() {
running.set(true);
}
public void methodB() {
if (!running.get()) {
return;
}
}
Will running.get() be guaranteed to see an update via running.set(true) or running.set(false) from another thread?
In your example, a simple volatile boolean would be enough, since you only seem to be doing atomic operations. AtomicBoolean is useful if you need the methods such as compareAndSet.
So in answer to your question, yes, when using a volatile boolean or an AtomicBoolean, other threads will see the updates to the variable.
Generally speaking these code blocks are not equal for methodB, because reading volatile variable does not create synchronization order.
Imagine you have some other field int x = 42 in your class, that is updated in methodB:
public void methodB() {
if (!running.get()) {
return;
}
if (x < 50) x++; // just example
}
Then you have several threads that call methodB:
when using synchronized keyword, updates are safe and visible to all threads.
when using AtomicBoolean/volatile visibility is broken
If there is no such case with variable updates and the task is just to guarantee visibility between methodA - methodB sequence, then it's OK - AtomicBoolean is enough for that.
Yes. From the Javadoc of AtomicBoolean:
A {#code boolean} value that may be updated atomically.
This means that any update to AtomicBoolean is indivisible. So, I would consider such use of AtomicBoolean to be thread safe.
You should still consider making the declaration of AtomicBoolean final:
private final AtomicBoolean running;
How can I access static variable from many thread simultaneously.
If I have a class like
Class A {
public static boolean FLG=false;
.....................
....................
}
And I need to access the value from thread 1 like
....................
public void run() {
boolean t1=A.FLG;
..................
}
and from thread 2 I need to set value like
....................
public void run() {
A.FLG=true;
..................
}
Does this cause memory violation ?. If so what is the recommended method to handle such a situation?.
If all you want to do is get and set a primitive you can make it volatile and it will be thread safe for those operations.
Wrap the static variable in a synchronized method and call the method as you like
public static synchronized void method1(){
//Whatever
}
public static synchronized void method2(){
//Whatever again
}
Note that there are other ways to synchronize access to a method. They are considered more efficient in environments busy threads accessing the same methods.
Check the ReentrantLock class. There are also answers for when to use synchronized and RentrantLock and many more information that could be found through google.
Also as peter's answer and muel's comment suggests. Marking the boolean variable as volatile should be helpful. volatile boolean variables will NOT cache it's initial value (false or true). The JVM could do that occasionally which could be unexpected by the programmer.
You may get some undesired situation where two threads try to set different values into the static variable and you won`t have sure what exactly value really is there. The best way (thinking in a simple scenario) I think it is using AtomicBoolean ( http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html ) and you get the value in the object and use it (instead of using the object all the time, due a different thread can change it and you might get unexpected scenario).
Another suggestion is to use Byteman to create concurrent tests.
Regards,
Luan
In Class A , you can create a set and get method for FLG like:
public static synchronized boolean getFlag()
{
return FLG;
}
public static synchronized setFlag(boolean flag)
{
FLG=flag;
}
Now from other Threads, access value of FLG usng this method. This will keep the value of FLG Consistent across multiple Threads.
If you do not want to use synchronized, ReentrantLock,
you can write your own logic for this.
Example:
public class A extends Thread{
public static boolean FLG=false;
public A(String threadName) {
start();
setName(threadName);
}
#Override
public void run() {
// TODO Auto-generated method stub
while(true){
if(this.getName().equals("getterThread") && FLG == true){
boolean t1=A.FLG;
}
if(this.getName().equals("setterThread") && FLG == false){
A.FLG = true;
}
}
}
public static void main(String[] args) {
A dad = new A("getterThread");
A son = new A("setterThread");
}
}
Not sure I understand threads correctly, could someone tell me whether I´m right or wrong in the following example:
class Task {
String taskName;
private Thread thread;
boolean isFinished;
public Task(String name){
taskName = name;
}
public void createTask(final Runnable r) {
thread = new Thread(r){
public void run(){
if(r != null) {
r.run();
isFinished = true;
}
}
};
thread.start();
}
}
What I'm actually doing in my app is that I set the isFinished to true, and have an observer that whenever the isFinished is true does some stuff. I'm afraid that isFinished is set to true, before all code in the Runnable I pass as parameter is actually terminated.
Isn't the run method suppose to put the code I pass, in a separate thread and run that code asynchronously?
Close, but your new thread is already given the runnable object to execute. You really want to give it a wrapper which runs the r.run() method and then sets isFinished.
Change:
public void createTask(final Runnable r) {
thread = new Thread(r){
public void run(){
if(r != null) {
r.run();
isFinished = true;
}
}
};
thread.start();
}
to
public void createTask(final Runnable r) {
thread = new Thread( new Runnable {
public void run(){
if(r != null) {
r.run();
isFinished = true;
}
}
});
thread.start();
}
I would be remiss if I didn't point out the thread-unsafetiness of isFinished. You will not be guaranteed to notice when the thread finishes, without adding synchronization. I recommend you add:
public synchronized boolean getIsFinished()
{
return isFinished;
}
public synchronized void setIsFinished(boolean finished)
{
isFinished = finished;
}
And use these methods to get or set the isFinished flag.
Given your lack of synchronization here, you may be seeing other thread-safety oddities, depending on whether or not your r.run() method and your other "observer" are sharing data without synchronization as well.
You should almost never pass a Runnable into the constructor of a Thread and override the Thread's run() method.
The following two pieces of code are essentially identical:
Runnable r = new Runnable( )
{
public void run( )
{
// do stuff...
}
};
new Thread( r ).start( );
An here's another way to accomplish the same thing by overriding run():
(new Thread( )
{
public void run( )
{
// do stuff...
}
}).start( );
The way you wrote your code, isFinished will not be set to true until r.run() is complete. It may be appearing otherwise because you may have some data visibility issues due to missing synchronization or missing volatile declarations.
It's a little bit odd since you're both passing in the Runnable to the constructor, but calling it using the reference from your method declaration, not the one inside the thread. But it "works", there's just a redundancy there.
As an aside, don't forget #Override in your anonymous class :)
No, the run method simply is a normal function, that you can override when extending the Thread class in order to implement your own behaviour.
It's the start method of the Thread class that starts a new thread and runs that code async.
Well your code is partially right, and partially wrong.
You are correct that isFinished will only be set to true once everything inside the runnable you are passing in the parameter has finished executing.
However, due to the particular semantics of the java memory model (I'll get into more details about that below), it is possible that when you set isFinished to true, that change is only visible to the thread that has set that variable to true. If you want your code to work as expected, you need to declare isFinished as volatile. This will make any changes you make to that variable immediately visible by other threads.
Another way to do it is to declare isFinished as AtomicBoolean rather than boolean. This class has many methods that allow you to check and set the boolean in an atomic way, helping you to avoid many common multithreading pitfalls.
I suggest you use the synchronization primitive specifically designed for your problem.
This primitive is called CountDownLatch.
Here is the updated code:
class Task {
String taskName;
private Thread thread;
CountDownLatch finishedSignal = new CountDownLatch( 1 );
public Task(String name){
taskName = name;
}
public void createTask(final Runnable r) {
thread = new Thread(r){
public void run(){
if(r != null) {
r.run();
finishedSignal.countDown( );
}
}
};
thread.start();
finishedSignal.await( );
}
}
You should use a FutureTask instead of your own Task class. It has an isDone() method, and it is integrated nicely with the Executor framework.
Most importantly the happens-before relationships are maintained as you expect it (actually in your code the problem is not that isFinished is set to true, before all code in the Runnable is terminated, but the other way: possibly it will not be set to true in the original thread even if the Runnable is terminated)
Example:
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("work done");
}
};
FutureTask<Void> task = new FutureTask<Void>(runnable, null);
ExecutorService es = Executors.newSingleThreadExecutor();
es.submit (task);
while (!task.isDone()) {
System.out.println("waiting...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
In Java Concurrency in Practice there is a sample that made me confused:
public class Novisibility {
private static boolean ready;
private static int number;
private static class ReaderThread implements Runnable {
public void run() {
while (!ready) {
Thread.yield();
}
System.out.println(number);
}
}
public static void main(String[] args) {
System.out.println("0");
new Thread(new ReaderThread()).run();
System.out.println("1");
number = 42;
System.out.println("2");
ready = true;
System.out.println("3");
}
}
I can understand reordering makes the loop to never break, but I can't understand why "1", "2" and "3" are never printed to console. Could any body help?
You don't spawn a new thread but run it in the current one. Use the start() method instead.
Since you run() executes on the main thread and that method runs in an endless loop you'll never reach the System.out.println() statements (and neither do you reach ready = true;).
From the JavaDoc on 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.
And start():
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.