I have a Runnable class like:
Class R1 implements Runnable {
private static final Log LOGGER = LogFactory.getLog(R1.class);
private final ObjectClass obj;
private final SomeService service;
public R1(ObjectClass obj, SomeService service) {
this.obj = obj;
this.service = service;
}
@override
public void run() {
String value = this.obj.getSomeValue();
LOGGER.debug("Value is " + value);
// some actions, such as:
// service.someMethod(obj);
}
}
I use a ExecutorService object to execute R1 and put R1 in a queue. But later outside R1 I change the value in the ObjectClass that I passed in R1 so the the actions in R1 after getSomeValue() aren't behaving as I expected. If I want to keep the value of ObjectClass object in R1 unchanged what can I do? Suppose the object is big and has a lot of get and set methods.
To make the problem clearer, I need to pass the obj into a service class object which is also used as a parameter in the runnable class. I have changed the original codes accordingly.
As per comments, apparently my suggested solution has problems.
As such, follow the other suggestions about creating a new instance and copying the properties you require across. Or create a lightweight data object that holds the properties you require. Either way, I believe you need 2 instances to do what you want.
I suggest you could implement clone method that creates a new instance.
http://download.oracle.com/javase/1,5,0/docs/api/java/lang/Cloneable.html
The problem here is that you have passed the instance into your R1class, but it is still the same single instance, so changes to it will affect everything else. So, implementing a clone method will allow you to easily create a copy of your instance that can be used in your R1 class, while allowing you to make further changes to your original.
In your R1 class,
public R1(ObjectClass obj) {
//this.obj = obj;
this.obj = obj.clone();
}
P.S. you must implement this method yourself. It won't just automatically give you a deep copy.
Depending on the nature of your program, there are a couple options.
You could "Override Clone Judiciously" (Item 11 in Effective Java) and clone the object before handing it to the runnable. If overriding clone doesn't work for you, it might be better to do one of the following:
obj
.obj
. So instead of passing obj
into the constructor, you would pass in someValue
. I would advocate this method, so that you only supply R1
with the data it needs, and not the entire object.
Alternatively, if it doesn't matter that the data in obj
changes before R1
is executed, then you only need to make sure that obj
doesn't change while R1
is executing. In this case, you could add the synchronize
keyword to the getSomeValue()
method, and then have R1
synchronize on obj
like so:
@Override
public void run() {
synchronize (obj) {
String value = obj.getSomeValue();
}
// some actions.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With