Reputation: 93
When I compile and run the StartThreads Class I get a list of integer 1 to 1000000 with false and at the end it prints true; Now what I'm trying to find out is why does class threadone print nothing when it should print once the instance variable in class MyVariables = true? public class MyVariables { public boolean startApp = false; }
public class ThreadOne implements Runnable {
Thread t;
MyVariables x;
public ThreadOne(MyVariables x) {
t = new Thread(this, "Thread One");
this.x = x;
}
@Override
public void run() {
while(this.x.startApp != false) {
System.out.println("Starting");
}
}
public void start() {
t.start();
}
}
public class ThreadTwo implements Runnable {
Thread t;
MyVariables x;
public ThreadTwo(MyVariables x) {
t = new Thread(this, "Thread One");
this.x = x;
}
@Override
public void run() {
synchronized(this.x) {
for(int i = 0; i <= 1000001; i++) {
if(i == 1000001) {
this.x.startApp = true;
System.out.println(this.x.startApp);
}
else {
System.out.println(this.x.startApp);
System.out.println(i);
}
}
}
}
public void start() {
t.start();
}
}
public class StartThreads {
public static void main(String[] args) {
MyVariables a = new MyVariables();
ThreadOne x = new ThreadOne(a);
ThreadTwo y = new ThreadTwo(a);
x.start();
y.start();
}
}
Upvotes: 1
Views: 104
Reputation: 285403
Why should ThreadOne behave as you're stating? It's while loop is never run but rather is skipped over since the condition is not true. I think that you're expecting it to wait for something to change to true, but it does nothing of the sort, and instead once it sees that a condition is false, finishes execution.
Note that this is ugly code:
while(this.x.startApp != false) {
Why state while something is not false? That's the same as being true. Better
while (x.startApp) {
Now as for your actual problem, perhaps you should instead make your while loop:
while (!x.startApp) {
Thread.sleep(1); // surrounded with try/catch
}
System.out.println("Starting");
e.g.,
class ThreadOne implements Runnable {
Thread t;
volatile MyVariables x;
public ThreadOne(MyVariables x) {
t = new Thread(this, "Thread One");
this.x = x;
}
@Override
public void run() {
while (!x.startApp) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
}
System.out.println("Starting");
}
public void start() {
t.start();
}
}
class ThreadTwo implements Runnable {
private static final int MAX_I = 10001;
Thread t;
volatile MyVariables x;
public ThreadTwo(MyVariables x) {
t = new Thread(this, "Thread One");
this.x = x;
}
@Override
public void run() {
synchronized (this.x) {
for (int i = 0; i <= MAX_I; i++) {
if (i == MAX_I) {
this.x.startApp = true;
System.out.println(this.x.startApp);
} else {
System.out.println(this.x.startApp);
System.out.println(i);
}
}
}
}
public void start() {
t.start();
}
}
public class StartThreads {
public static void main(String[] args) {
MyVariables a = new MyVariables();
ThreadOne x = new ThreadOne(a);
ThreadTwo y = new ThreadTwo(a);
x.start();
y.start();
}
}
class MyVariables {
public volatile boolean startApp = false;
}
Also, I think that your boolean field should at the least be volatile.
Another way using a PropertyChangeListener and the observer pattern:
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class StartThreads2 {
public static void main(String[] args) {
final MyVariables2 myVars2 = new MyVariables2();
final RunOne runOne = new RunOne();
final RunTwo runTwo = new RunTwo(myVars2);
myVars2.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (MyVariables2.START_APP.equals(pcEvt.getPropertyName())) {
if (pcEvt.getNewValue().equals(Boolean.TRUE)) {
new Thread(runOne).start();
}
}
}
});
new Thread(runTwo).start();
}
}
class MyVariables2 {
public static final String START_APP = "start app";
private volatile boolean startApp = false;
private PropertyChangeSupport pcSupport = new PropertyChangeSupport(this);
public boolean isStartApp() {
return startApp;
}
public void setStartApp(boolean startApp) {
boolean oldValue = this.startApp;
boolean newValue = startApp;
this.startApp = startApp;
pcSupport.firePropertyChange(START_APP, oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
}
class RunOne implements Runnable {
@Override
public void run() {
System.out.println("Starting RunOne");
}
}
class RunTwo implements Runnable {
private static final int MAX_I = 10001;
private MyVariables2 myVars2;
public RunTwo(MyVariables2 myVars2) {
this.myVars2 = myVars2;
}
@Override
public void run() {
for (int i = 0; i <= MAX_I; i++) {
System.out.println("startApp: " + myVars2.isStartApp());
System.out.printf("i: %05d%n", i);
}
myVars2.setStartApp(true);
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
System.out.println("startApp: " + myVars2.isStartApp());
}
}
Upvotes: 3