I'm having an issue that cropped up in multithreading. I have an enum
with state set through setters
instead of the constructor. I'll have 2 threads that make instances of this enum
for different uses. Each thread will have its own use for this setter. Each thread will have multiple instances of these enums floating around.
My problem is that when I call the setter in one thread and it's immediately called in another thread, the state in the initial enum is overwritten by what was provided to the setter in the second enum.
I have provided a MWE below. How do I fix this issue?
This isn't just a problem in a multi-threaded context, but I would like the solution to be thread-safe as well.
Note also that I use reference based testing, e.g. if(enumValue == TestEnumMutate.A)
must return true if enumValue
is indeed A
.
enum TestEnumMutate {
A(0),
B(0);
int i;
TestEnumMutate(int i) {
this.i=i;
}
public void setI(int i) {
this.i=i;
}
public void print() {
System.out.println(i);
}
}
class TestClassMutate {
private int i = 0;
public TestClassMutate() { }
public void setI(int i) {
this.i=i;
}
public void print() {
System.out.println(i);
}
}
public class ThreadSafeTest implements Runnable{
private boolean sleep;
private boolean isTestingEnum;
public ThreadSafeTest(boolean sleep,boolean isTestingEnum) {
this.sleep=sleep;
this.isTestingEnum=isTestingEnum;
}
public void run() {
if(isTestingEnum) {
this.runEnumTest(sleep);
} else {
this.runClassTest(sleep);
}
}
private void runClassTest(boolean sleep) {
TestClassMutate foo = new TestClassMutate();
if(sleep) {
try {
Thread.sleep(500);
} catch(Exception e) {};
} else {
foo.setI(1);
}
foo.print();
}
private void runEnumTest(boolean sleep) {
final TestEnumMutate foo = TestEnumMutate.A;
if(sleep) {
try {
Thread.sleep(500);
} catch(Exception e) {};
} else {
foo.setI(1);
}
foo.print();
}
public static void main(String[] args) throws Exception {
System.out.println("Should print 1 then 0 if one thread's instance didn't"+
" interfere with the other thread's instance");
Thread enumTestThread1 = new Thread(new ThreadSafeTest(true,true));
Thread enumTestThread2 = new Thread(new ThreadSafeTest(false,true));
enumTestThread1.start();
enumTestThread2.start();
enumTestThread1.join();
enumTestThread2.join();
System.out.println("Should print 1 then 0 if one thread's instance didn't"+
" interfere with the other thread's instance");
Thread classTestThread1 = new Thread(new ThreadSafeTest(true,false));
Thread classTestThread2 = new Thread(new ThreadSafeTest(false,false));
classTestThread1.start();
classTestThread2.start();
classTestThread1.join();
classTestThread2.join();
}
}