Queueing Methods With Java 8 - java

I am building a game simulator that has hundreds of micro steps like the following. They each perform a unique task, but I left out the implementation details for the sake of brevity.
public class Sim {
static void phase() {
phaseIn();
phaseOut();
}
static void untap() {
}
static void upkeep() {
}
static void draw() {
}
...
}
A Turn usually involves executing steps sequentially, but there are times when a special effect may cause the sequence to change. For example, I may be required to repeat a step twice, skip a step, or rearrange the order of the steps. These actions are all special cases, as the turn typically just occurs in order from start to finish.
For example, the following series of events represents my normal turn.
... > upkeep() > draw() > preCombatMain() > ...
Now, I play something that requires me to repeat my draw step. I need my turn to look like this:
... > upkeep() > draw() > draw() > preCombatMain() > ...
The steps of a turn are methods, and I do not know how to enqueue or dequeue methods. I know that Java 8 has method references, but the feature is relatively new. I have been unable to apply existing tutorials to what I am trying to accomplish. I got as far as Sim::untap, but I have no idea how to assign it, invoke it, etc. How do I queue methods in Java 8, or otherwise call methods in an order determined at run-time by the choices a player makes?
Note: I realize that my inability to understand may be due to a fundamental design flaw. I have never taken a game design course, I am completely open to criticism, and I will change my design if it is flawed. That said, the question is not to be misconstrued as "Please recommend a design pattern." I considered an alternate design, where I "number" each step in a massive switch statement, queue "numbers", and repeatedly switch on the front of the queue, but that seemed like a poor plan (in my opinion).

If you simply want them to run sequentially, you can of course call them one after the other. If the order can change, an alternative is to use a queue of method references:
LinkedList<Runnable> queue = new LinkedList<>();
queue.add(Sim::upkeep);
queue.add(Sim::draw);
queue.add(Sim::preCombatMain);
queue.forEach(Runnable::run);
I was able to use a LinkedList<Runnable> because the signature of your methods is void m(). For other signatures you can use other types, for example:
void m() use Runnable
T m() use Supplier<T>
void m(T o) use Consumer<T>
R m(T o) use Function<T, R>

The solution is to use polymorphism. Define an interface for the step:
interface Step {
void process();
}
Then define each step by implementing it:
class UpkeepStep implements Step {
void process() { ... }
}
Now you can put all your steps in an array, shuffle it, if needed, and execute all steps, like this:
for (Step step : steps) {
step.process();
}
An alternative approach that may run faster, is to generate code that contains the method calls, compile it and load the class. However, it gives you only better performance if the step does not take much runtime compared to the method call overhead and if you execute each generated piece of code a lot, so the JIT will optimize it.

Related

Correct syntax for making a functional interface instance automatically call its method

I've been watching Douglas Schmidt classes on Parallel Java. He introduces Lambda x method referencing syntax discussion, highlighting how the last one is preferable, as it makes clearer what the code is actually doing, not what the programmer is trying to do with the code, even more than forEach approach.
String[] names = {"first", "Second", "third"};
Arrays.sort(names, (n1,n2) -> n1.compareToIgnoreCase(n2));
Arrays.sort(names, String::compareToIgnoreCase); //preferable
For example, that approach mitigates the chances of programmer making mistakes inside lambda function: passing the wrong argument, inverting arguments order, adding collateral effects, etc.
Then he introduces Functional interfaces, an interface that contains only an abstract method, implementing its own interface runTest with an abstract method factorial():
private static <T> void runTest(Function<T,T> factorial, T n) {
System.out.println(n+ " factorial = " + factorial.apply(n));
}
private static class ParallelStreamFactorial{
static BigInteger factorial(BigInteger n) {
return LongStream
.rangeClosed(1, n.longValue())
.parallel()
.mapToObj(BigInteger::valueOf)
.reduce(BigInteger.ONE, BigInteger::multiply);
}
}
Calling it with the following syntax:
import java.math.BigInteger;
import java.util.function.Function;
import java.util.stream.LongStream;
public static void main(String[] args) {
BigInteger n = BigInteger.valueOf(3);
runTest(ParallelStreamFactorial::factorial, n);
}
The code works and prints
3 factorial = 6
As I'm studying lambdas, I tried to interchange method reference syntax for lambda syntax, and managed to using:
public static void main(String[] args) {
BigInteger n = BigInteger.valueOf(3);
runTest((number)->ParallelStreamFactorial.factorial(number), n);
}
Which also worked.
Then he proceeds to explain built-in interfaces, such as Predicate<T>{boolean test(T t);}, and that's where I got stuck.
I managed to implement a Predicate<Integer> that tests if the integer is bigger than 0 using the three syntaxes:
Instantiating an object myPredicate from a class that implements Predicate<Integer>
Instantiating an object lambdaPredicate from a lambda
Instantiating an object methodReferencePredicatefrom a method reference:
import java.util.function.Function;
import java.util.function.Predicate;
public class MyPredicates {
public static void main(String[] args) {
Predicate<Integer> constructorPredicate = new myPredicate();
System.out.println(constructorPredicate.test(4));
Predicate<Integer> lambdaPredicate = (number)-> number > 0;
System.out.println(lambdaPredicate.test(4));
Predicate<Integer> methodReferencePredicate = myMethodReference::myTest;
System.out.println(methodReferencePredicate.test(4));
}
private static class myPredicate implements Predicate<Integer>{
public boolean test(Integer t) {
return t>0;
}
}
private static class myMethodReference{
public static boolean myTest(Integer t) {
return t>0;
}
}
}
And then calling their .test() methods. They're all three working and printing true.
However I would like to "instantiate and call" everything in a single line, as he did in his example. It seems like his code is inferring the type of the argument passed (I may be wrong) but it's definitely running automatically.
I tried different things:
Predicate<Integer>(myMethodReference::myTest, 4);
Predicate(myMethodReference::myTest, 4);
Predicate<Integer>((number) -> myMethodReference.myTest(number), 4);
Predicate((number) -> myMethodReference.myTest(number), 4);
But none of them work.
They throw:
Syntax error, insert ";" to complete LocalVariableDeclarationStatement
and
The method Predicate(myMethodReference::myTest, int) is undefined for the type MyPredicates
Errors. I also don't even know the name of what he's doing in that single line to properly search better on internet for references.
What's the correct syntax for that, whether by method reference or lambdas?
You've made things far too complicated.
There is no point in lambdas if you want to 'execute them immediately'.
Here is how you run your my test code 'immediately':
System.out.println(number > 4);
Why mess with lambdas? They just make matters confusing here.
The very point of a lambda is two-fold:
A way to transmit code itself to other contexts.
Control flow abstraction.
In java in particular, option 2 is an evil - it makes code ugly, harder to reason about, introduces pointless distractions, and in general should be avoided... unless you're employing it to avoid an even greater evil. That happens plenty - for example, a reasonable 'stream chain' is generally better even though its control flow abstraction. I'd say this:
int total = list.stream()
.filter(x -> x.length() < 5)
.mapToInt(Integer::valueOf)
.sum();
is the lesser evil compared to:
int total = 0;
for (var x : list) {
if (x.length() < 5) continue;
total += Integer.parseInt(x);
}
but it is a pretty close call.
Why is it 'evil'? Because lambdas in java are non transparent in 3 important ways, and this non-transparency is a good thing in the first case, but a bad thing in the second. Specifically, lambdas are not transparent in these ways:
Lambdas cannot change or even read local variables from outer scope unless they are (effectively) final.
Lambdas cannot throw checked exceptions even if the outer scope would handle them (because they catch them or the method you're in declared throws ThatException).
Lambdas cannot do control flow. You can't break, continue, or return from within a lambda to outside of it.
These 3 things are all useful and important things to be doing when you're dealing with basic control flow. Therefore, lambdas should be avoided as you create a bunch of problems and inflexibility by using them... unless you've avoided more complexity and inflexibility of course. It's programming: Nothing is ever easy.
The notion of bundling up code is therefore much more useful, because those non-transparencies turn into upside:
If you take the lambda code and export it to someplace that runs that code much later and in another thread, what does it even mean to modify a local variable at that point? The local variable is long gone (local vars are ordinarily declared on stack and disappear when the method that made them ends. That method has ended; your lambda survived this, and is now running in another context). Do we now start marking local vars as volatile to avoid thead issues? Oof.
The fact that the outer code deals with a checked exception is irrelevant: The lexical scope that was available when you declared the lambda is no longer there, we've long ago moved past it.
Control flow - breaking out of or restarting a loop, or returning from a method. What loop? What method? They have already ended. The code makes no sense.
See? Lambda lack of transparency is in all ways great (because they make no sense), if your lambda is 'travelling'. Hence, lambdas are best used for this, they have no downsides at that point.
Thus, let's talk about travelling lambdas: The very notion is to take code and not execute it. Instead, you hand it off to other code that does whatever it wants. It may run it 2 days from now when someone connects to your web server, using path /foobar. It may run every time someone adds a new entry to a TreeSet in order to figure out where in the tree the item should be placed (that's precisely the fate of the lambda you pass to new TreeSet<X>((a, b) -> compare-a-and-b-here).
Even in control flow situations (which are to be avoided if possible), your lambda still travels, it just travels to place that does immediately ends up using it, but the point of the lambda remains control flow abstraction: You don't run the code in it, you hand your lambda off to something else which will then immediately run that 0 to many times. That's exactly what is happening here:
list.forEach(System.out::println);
I'm taking the code notion of System.out.println(someString), and I don't run it - no, I bundle up that idea in a lambda and then pass this notion to list's forEach method which will then invoke it for me, on every item in the list. As mentioned, this is bad code, because it needlessly uses lambdas in control flow abstraction mdoe which is inferior to just for (var item : list) System.out.println(item);, but it gets the point across.
It just doesn't make sense to want to write a lambda and immediately execute it. Why not just... execute it?
In your example from the book, you don't actually execute the lambda as you make it. You just.. make it, and hand it off to the runTest method, and it runs it. The clue is, runTest is a method (vs your attempts - Predicate is not a method), it's not magical or weird, just.. a method, that so happens to take a Function<A, B> as argument, and the lambda you write so happens to 'fit' - it can be interpreted as an implementation of Function<A, B>, and thus that code compiles and does what it does.
You'd have to do the same thing.
But, if that code is a single-use helper method, then there's no point to the lambda in the first place.

Java store reflected Method statically in class: Safe?

Is something like the following 'safe' in Java, and why?
public final class Utility {
private Utility() {}
private static Method sFooMethod = null;
public static void callFoo(SomeThing thing) {
try {
if(sFooMethod == null)
sFooMethod = SomeThing.class.getMethod("foo");
sFooMethod.invoke(thing);
} catch(Exception e) {} // Just for simplicity here
}
}
My rationale would be that even if another thread writes to sFooMethod in the background and the current thread sees it suddenly somewhere during execution of callFoo(), it would still just result in the same old reflective invoke of thing.foo()?
Extra question: In what ways does the following approach differ (positive/negative) from the above? Would it be preferred?
public final class Utility {
private Utility() {}
private static final Method sFooMethod;
static {
try {
sFooMethod = SomeThing.class.getMethod("foo");
} catch(Exception e) {}
}
public static void callFoo(SomeThing thing) {
try {
if(sFooMethod != null)
sFooMethod.invoke(thing);
} catch(Exception e) {}
}
}
Background update from comment:
I am writing an Android app and I need to call a method that was private until API 29, when it was made public without being changed. In an alpha release (can't use this yet) of the AndroidX core library Google provides a HandlerCompat method that uses reflection to call the private method if it is not public. So I copied Google's method into my own HandlerCompatP class for now, but I noticed that if I call it 1000 times, then the reflective lookup will occur 1000 times (I couldn't see any caching). So that got me thinking about whether there is a good way to perform the reflection once only, and only if needed.
"Don't use reflection" is not an answer here as in this case it is required, and Google themselves intended for it to happen in their compatibility library. My question is also not whether using reflection is safe and/or good practice, I'm well aware it's not good in general, but instead whether given that I am using reflection, which method would be safe/better.
The key to avoiding memory consistency errors is understanding the happens-before relationship. This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement.
Java language specification states following:
17.4.5. Happens-before Order
Two actions can be ordered by a happens-before relationship. If one
action happens-before another, then the first is visible to and
ordered before the second.
If we have two actions x and y, we write hb(x, y) to indicate that x
happens-before y.
If x and y are actions of the same thread and x comes before y in
program order, then hb(x, y).
As, in your case, writing to and then reading from the static field are happening in same tread. So the `happens before' relation is established. So the read operation will always see effects of the write operation.
Also, all threads are going to write same data. At worse, all eligible threads will write to the variable same time. The variable will have reference to the object that got assigned last and rest of the dereferenced objects will be garbage collected.
There won't be many threads in your App which will enter the same method at once, which will cause significant performance hit due to lot of object creation. But if you want to set the variable only once then second approach is better. As static blocks are thread safe.
Is something like the following 'safe' in Java, and why?
No I would not recommend using reflections, unless you have to.
Most of the time developers design their classes in a way, so that access to a hidden field or method is never required. There will most likely be a better way to access the hidden content.
Especially hidden fields and methods could change their name, when the library they are contained in is updated. So your code could just stop working suddenly and you would not know why, since the compiler would not output any errors.
It is also faster to directly access a method or field then through reflections, because the reflections first need to search for it and the direct access don't
So don't use reflections if you don't have to
I'm not sure what your goal is -- there is probably a better way to do what you're trying to do.
The second approach, with a static initializer, is preferable because your first implementation has a race condition.

Command Pattern with additional argument parsing

Recently I have really focused on design patterns and implementing them to solve different problems. Today I am working on the Command Pattern.
I have ended up creating an interface:
public interface Command {
public void execute();
}
I have several concrete implementations:
public class PullCommand implements Command {
public void execute() {
// logic
}
}
and:
public class PushCommand implements Command {
public void execute() {
// logic
}
}
There are several other commands as well.
Now.. the thing is there's a BlockingQueue<Command> which runs on a different thread using .take() to retrieve queued commands and execute them as they come in (I'd call this Executor class below) by another class which produces them by parsing the user input and using .queue(). So far so good...
The hard part about me is parsing the command (CLI application).
I have put all of them in a HashMap:
private HashMap<String, Command> commands = new HashMap<String, Command>();
commands.put("pull", new PullCommand());
commands.put("push", new PushCommand());
//etc..
When user inputs a command, the syntax is such that one thing is for sure, and it is that the "action" (pull / push) comes as first argument, so I can always do commands.get(arguments[0]) and check if that is null, if it is, then the command is invalid, if it isn't, then I have successfully retrieved an object that represents that command. The tricky part is that there are other arguments that also need to be parsed and for each command the algorithm for parsing it, is different... Obviously one thing I can do is put the arguments[] as a parameter to the method execute() and end up having execute(String[] args) but that would mean I have to put the parsing of arguments inside the execute() method of the command, which I would like to avoid for several reasons:
The execution of Command happens on a different thread that uses a BlockingQueue, it executes a single command, then another one etc.. The logic I would like to put inside execute() has to ONLY be the execution of the command itself, without the parsing or any for example heavy tasks which would slow the execution (I do realize parsing several args would not mess up the performance that much.. but here I am learning structural designs and ways to build good coding habits and nice solutions. This would not be perfect by any mean)
It makes me feel like I am breaking some fundamental principles of the "Command" pattern. (Even if not so, I'd like to think of a better way to solve this)
It is obvious that I cannot use the constructor of the concrete commands since HashMap returns already initialized objects. Next thing that comes to mind is using another method inside the object that "processes" (process(String[] args)) the arguments and sets private variables to the result of the parsing and this process(String[] args) method is called by the Producer class before doing queue() on the command, so the parsing would end up OUT of the Executor class (thread) and Point 1. from above would not be a problem.
But there's another problem.. What happens if a user enters a lot of commands to the application, the application does .get(args[0]) on the arguments and retrieves a PullCommand, it uses the process(String[] args) and private variables are set, so the command is queued to the Executor class and it is waiting to be executed. Meanwhile.. another command is input by the user, .get(args[0]) is used again, it retrieves a PullCommand from the HashMap (but that PullCommand is the same as the one that is queued for execution) and process() would be called BEFORE the command has been executed by the Executor class and it would screw up the private variables. We would end up with 2 PullCommands records in the BlockingQueue, second one would be correct from user point of view (since he input what he wants it to do and it does just that), but first one will be the same as the second one (since it is the same object) and it would not correspond to the initial arguments.
Another thing I thought of is using a Factory class that implements the parsing for each of the commands and returns the appropriate Command object.
This would mean though, that I need to change the way HashMap is used and instead of Command I have to use the Factory class instead:
HashMap<String, CommandFactory> commands = new HashMap<String, CommandFactory>();
commands.put("pull", new CommandFactory("pull"));
commands.put("pull", new CommandFactory("push"));
and based on the String passed to the Factory, its process() method would use the appropriate parsing for that command and it would return the corresponding Command object, but this would mean that this class could potentially be very big because of containing the parsing for all commands..
Overall, this seems like my only option, but I am very hesitant since from structural point of view, I don't think I am solving this problem nicely. Is this a nice way to deal with this situation? Is there anything I am missing? Is there any way I can maybe refactor part of my code to ease it?
You are over thinking this. The command pattern is basically "keep everything you need to know how do something and do it later", so it's OK to pass stuff to the execution code.
Just do this:
user inputs a String[]
first string is the command "name" (use it as you are now)
the remaining strings are the parameters to the command (if any)
change your interface to public void execute(String[] parameters);
to execute, pass the parameters to the command object
Throwing a design question broadly like this in SO is in general not a good idea. It's a bit surprising to only see a downvote with no close request.
In any case, without understanding your problem thoroughly, it's hard to say what's the "best" design, not to mention if it I did, I won't call anything to be the best. Therefore I will stick with what I say by using Builder pattern.
In general, a builder pattern is used whenever the logic of construction is too complicated to fit in constructor, or it's necessarily divided into phases. In this case, if you want some extreme diversity of how your commands should look like depending on action, then you will want some builder like this:
interface CommandBuilder<T extends Command> {
void parseArgs(String[] args);
T build();
}
Generic here is optional if you don't plan to use these builders more than your current architecture, otherwise it's beneficial to be more precise in the types. parseArgs is responsible for those necessary parsing you were referring to. build should spit out an instance of Command depending on your current arguments.
Then you want your dispatcher map to look like this:
HashMap<String, Supplier<? extends CommandBuilder<? extends Command>>> builders = new HashMap<>();
commands.put("pull", () -> new PullBuilder());
commands.put("push", () -> new PushBuilder());
// etc
Any of these builders can potentially have extremely complicated logic, as you would desire. Then you can do
CommandBuilder builder = builders.get(args[0]).get();
builder.setArgs(args);
queue.add(builder.build());
In this way, your Command interface can focus on what exact it's supposed to do.
Notice that after your builders map is built, everything goes statically, and mutation is localized. I don't fully understand what's your concern, but it should be addressed by doing this.
However, it could be an overkill design, depending on what you want to do.

Critical loop containing many “if” whose output is constant : How to save on condition tests ? For Java ;)

I just read this thread Critical loop containing many "if" whose output is constant : How to save on condition tests?
and this one Constant embedded for loop condition optimization in C++ with gcc which are exactly what I would like to do in Java.
I have some if conditions called many times, the conditions are composed of attributes define at initialization and which won't change.
Will the Javac optimize the bytecode by removing the unused branches of the conditions avoiding to spend time testing them?
Do I have to define the attributes as final or is it useless?
Thanks for you help,
Aurélien
Java compile time optimization is pretty lacking. If you can use a switch statement it can probably do some trivial optimizations. If the number of attributes is very large then a HashMap is going to be your best bet.
I'll close by saying that this sort of thing is very very rarely a bottleneck and trying to prematurely optimize it is counterproductive. If your code is, in fact, called a lot then the JIT optimizer will do its best to make your code run faster. Just say what you want to happen and only worry about the "how" when you find that's actually worth the time to optimize it.
In OO languages, the solution is to use delegation or the command pattern instead of if/else forests.
So your attributes need to implement a common interface like IAttribute which has a method run() (or make all attributes implement Runnable).
Now you can simply call the method without any decisions in the loop:
for(....) {
attr.run();
}
It's a bit more complex if you can't add methods to your attributes. My solution in this case is using enums and an EnumMap which contains the runnables. Access to an EnumMap is almost like an array access (i.e. O(1)).
for(....) {
map.get(attr).run();
}
I don't know about Java specifics regarding this, but you might want to look into a technique called Memoization which would allow you to look up results for a function in a table instead of calling the function. Effectively, memoization makes your program "remember" results of a function for a given input.
Try replacing the if with runtime polymorphism. No, that's not as strange as you think.
If, for example you have this:
for (int i=0; i < BIG_NUMBER; i++) {
if (calculateSomeCondition()) {
frobnicate(someValue);
} else {
defrobnicate(someValue);
}
}
then replace it with this (Function taken from Guava, but can be replaced with any other fitting interface):
Function<X> f;
if (calculateSomeCondition()) {
f = new Frobnicator();
else {
f = new Defrobnicator();
}
for int (i=0; i < BIG_NUMBER; i++) {
f.apply(someValue);
}
Method calls are pretty highly optimized on most modern JVMs even (or especially) if there are only a few possible call targets.

Determining synchronization scope?

in trying to improve my understanding on concurrency issues, I am looking at the following scenario (Edit: I've changed the example from List to Runtime, which is closer to what I am trying):
public class Example {
private final Object lock = new Object();
private final Runtime runtime = Runtime.getRuntime();
public void add(Object o) {
synchronized (lock) { runtime.exec(program + " -add "+o); }
}
public Object[] getAll() {
synchronized (lock) { return runtime.exec(program + " -list "); }
}
public void remove(Object o) {
synchronized (lock) { runtime.exec(program + " -remove "+o); }
}
}
As it stands, each method is by thread safe when used standalone. Now, what I'm trying to figure out is how to handle where the calling class wishes to call:
for (Object o : example.getAll()) {
// problems if multiple threads perform this operation concurrently
example.remove(b);
}
But as noted, there is no guarantee that the state will be consistent between the call to getAll() and the calls to remove(). If multiple threads call this, I'll be in trouble. So my question is - How should I enable the developer to perform the operation in a thread safe manner? Ideally I wish to enforce the thread safety in a way that makes it difficult for the developer to avoid/miss, but at the same time not complicated to achieve. I can think of three options so far:
A: Make the lock 'this', so the synchronization object is accessible to calling code, which can then wrap the code blocks. Drawback: Hard to enforce at compile time:
synchronized (example) {
for (Object o : example.getAll()) {
example.remove(b);
}
}
B: Place the combined code into the Example class - and benefit from being able to optimize the implementation, as in this case. Drawback: Pain to add extensions, and potential mixing unrelated logic:
public class Example {
...
public void removeAll() {
synchronized (lock) { Runtime.exec(program + " -clear"); }
}
}
C: Provide a Closure class. Drawback: Excess code, potentially too generous of a synchronization block, could in fact make deadlocks easier:
public interface ExampleClosure {
public void execute(Example example);
}
public Class Example {
...
public void execute(ExampleClosure closure) {
synchronized (this) { closure.execute(this); }
}
}
example.execute(new ExampleClosure() {
public void execute(Example example) {
for (Object o : example.getAll()) {
example.remove(b);
}
}
}
);
Is there something I'm missing? How should synchronization be scoped to ensure the code is thread safe?
Use a ReentrantReadWriteLock which is exposed via the API. That way, if someone needs to synchronize several API calls, they can acquire a lock outside of the method calls.
In general, this is a classic multithreaded design issue. By synchronizing the data structure rather than synchronizing concepts that use the data structure, it's hard to avoid the fact that you essentially have a reference to the data structure without a lock.
I would recommend that locks not be done so close to the data structure. But it's a popular option.
A potential technique to make this style work is to use an editing tree-walker. Essentially, you expose a function that does a callback on each element.
// pointer to function:
// - takes Object by reference and can be safely altered
// - if returns true, Object will be removed from list
typedef bool (*callback_function)(Object *o);
public void editAll(callback_function func) {
synchronized (lock) {
for each element o { if (callback_function(o)) {remove o} } }
}
So then your loop becomes:
bool my_function(Object *o) {
...
if (some condition) return true;
}
...
editAll(my_function);
...
The company I work for (corensic) has test cases extracted from real bugs to verify that Jinx is finding the concurrency errors properly. This type of low level data structure locking without higher level synchronization is pretty common pattern. The tree editing callback seems to be a popular fix for this race condition.
I think everyone is missing his real problem. When iterating over the new array of Object's and trying to remove one at a time the problem is still technically unsafe (though ArrayList implantation would not explode, it just wouldnt have expected results).
Even with CopyOnWriteArrayList there is the possibility that there is an out of date read on the current list to when you are trying to remove.
The two suggestions you offered are fine (A and B). My general suggestion is B. Making a collection thread-safe is very difficult. A good way to do it is to give the client as little functionality as possible (within reason). So offering the removeAll method and removing the getAll method would suffice.
Now you can at the same time say, 'well I want to keep the API the way it is and let the client worry about additional thread-safety'. If thats the case, document thread-safety. Document the fact that a 'lookup and modify' action is both non atomic and non thread-safe.
Today's concurrent list implementations are all thread safe for the single functions that are offered (get, remove add are all thread safe). Compound functions are not though and the best that could be done is documenting how to make them thread safe.
I think j.u.c.CopyOnWriteArrayList is a good example of similar problem you're trying to solve.
JDK had a similar problem with Lists - there were various ways to synchronize on arbitrary methods, but no synchronization on multiple invocations (and that's understandable).
So CopyOnWriteArrayList actually implements the same interface but has a very special contract, and whoever calls it, is aware of it.
Similar with your solution - you should probably implement List (or whatever interface this is) and at the same time define special contracts for existing/new methods. For example, getAll's consistency is not guaranteed, and calls to .remove do not fail if o is null, or isn't inside the list, etc. If users want both combined and safe/consistent options - this class of yours would provide a special method that does exactly that (e.g. safeDeleteAll), leaving other methods close to original contract as possible.
So to answer your question - I would pick option B, but would also implement interface your original object is implementing.
From the Javadoc for List.toArray():
The returned array will be "safe" in
that no references to it are
maintained by this list. (In other
words, this method must allocate a new
array even if this list is backed by
an array). The caller is thus free to
modify the returned array.
Maybe I don't understand what you're trying to accomplish. Do you want the Object[] array to always be in-sync with the current state of the List? In order to achieve that, I think you would have to synchronize on the Example instance itself and hold the lock until your thread is done with its method call AND any Object[] array it is currently using. Otherwise, how will you ever know if the original List has been modified by another thread?
You have to use the appropriate granularity when you choose what to lock. What you're complaining about in your example is too low a level of granularity, where the lock doesn't cover all the methods that have to happen together. You need to make methods that combine all the actions that need to happen together within the same lock.
Locks are reentrant so the high-level method can call low-level synchronized methods without a problem.

Categories