java - CopyOnWriteArrayList iteration inconsistancy with multithreading? -
i'm sending batches of strings in copyonwrite arraylists executorservice processed in parallel, runnable task processing these lists need iterate on list , processing on each string.
after running issues concurrency regular arraylists, tried use copyonwritearraylists because they're thread-safe, results inconsistent. is, different results on every run of program, suggesting contents of arraylist changed in way before each runnable taks can iterate on it.
public static class batchrunnable implements runnable { private copyonwritearraylist<string> batch; batchrunnable(copyonwritearraylist<string> batch){ this.batch = batch; } @override public void run(){ //iterate on batch , work string elements //make no modifications batch } }
the runnable task makes no modifications arraylist, iterates on list , uses string elements of list processing.
the place in copyonwritearraylist changed @ instantiation each new runnable task.
when passing in single strings instead of batching, had consistent , correct results, when began use batches in string arraylists, got inconsistent results, suggesting compromising concurrency of copyonwritearraylist batch, despite being supposedly thread-safe.
any appreciated, thanks!
edit: here batches being constructed:
runnable worker = null; while((line = br.readline()) != null) { recordbatch.add(line); if(recordbatch.size() == 100){ worker = new batchrunnable(recordbatch); executor.execute(worker); recordbatch.clear(); } } executor.shutdown(); executor.awaittermination(60,timeunit.seconds);
look while
loop:
while((line = br.readline()) != null) { recordbatch.add(line); if(recordbatch.size() == 100){ worker = new batchrunnable(recordbatch); executor.execute(worker); recordbatch.clear(); } }
you passing reference same list
in batchrunnable
. so, change list
@ 1 place, reflected in reference. so, once clear list using recordbatch.clear()
, list empty references, 1 having in batchrunnable
. why getting inconsistent result.
you should pass copy
of recordbatch
list in batchrunnable
:
worker = new batchrunnable(new arraylist<string>(recordbatch));
Comments
Post a Comment