Let's say I have ThreadPoolExecutor and BlockingQueue in the class:
class Test {
private final SomeSharedData sharedField;
private OkHttpClient httpClient;
private ThreadPoolExecutor executor;
private BlockingQueue<String> blockingQueue;
public void doWork(){
...
}
}
And in this class I have method doWork()
that is reading from this queue in a while(true)
loop. It is doing some work with HTTP and sharedField
. Is it okay if I will add in the executor multiple callings of this method? Like this:
executor.execute(this::doWork);
executor.execute(this::doWork);
Is it normal way to use it like this, I'm concerned because the threads will be using one method of the same object, or should I write a class that will implement runnable with doWork()
logic (normal way)? I know, there might be a problem with synchronization, because threads will be working with the fields of this object, but I will synchronize the fields I need when I'm using them, if I do it, is it normal to use it like this or there might be another problems?
CodePudding user response:
You are right to be cautious
Unfortunately, with concurrent processing, tests might succeed many times but then randomly fail because of a different winner in race conditions, so I'd be cautious in trusting them (unless you write very good concurrency tests). Also, when talking about synchronization, it is pretty hard to be sure it's right without getting down to the code and knowing what's expected and what state changes are valid.
Unless SomeSharedData
is read-only after you pass it to this Test
, I'd be very careful..
You say you'll "synchronize the fields I need when I'm using them" but that might not be enough, just because your calls wait in line to read/write the fields doesn't mean you've synchronized correctly. If something changes a field of SomeSharedData
while a doWork()
thread is running then it could read the field as one value at one moment then another value the next, which could potentially break some things..
Couldn't fit this in a comment.