java - Synchronise ArrayList over two threads -
i'm having difficult time understanding how synchronise arraylist on 2 threads. basically, want 1 thread appending objects list , other 1 reading list @ same time.
here class deploys threads:
public class main { public static arraylist<good> goodlist = new arraylist(); public static void main(string[] args) { thread thread1 = new thread(new goodcreator()); thread thread2 = new thread(new weightcounter()); thread1.start(); thread2.start(); } }
then 2 runnable classes:
this 1 reads lines of 2 values text file , appends new objects.
public class goodcreator implements runnable{ private arraylist<good> goodlist = main.goodlist; private static scanner scan; @override public void run() { system.out.println("thread 1 started"); int objcount = 0; try { scan = new scanner(new file(system.getproperty("user.home") + "//goods.txt")); } catch (filenotfoundexception e) { system.out.println("file not found!"); e.printstacktrace(); } while(scan.hasnextline()){ string line = scan.nextline(); string[] words = line.split("\\s+"); synchronized(goodlist){ goodlist.add(new good(integer.parseint(words[0]), integer.parseint(words[1]))); objcount++; } if(objcount % 200 == 0) system.out.println("created " + objcount + " objects"); } } }
this iterates on arraylist , supposed sum 1 of fields.
public class weightcounter implements runnable{ private arraylist<good> goodlist = main.goodlist; @override public void run() { system.out.println("thread 2 started"); int weightsum = 0; synchronized(goodlist){ for(good g : goodlist){ weightsum += g.getweight(); } } system.out.println(weightsum); } }
no matter input, weightsum never gets incremented , stays 0
thread 1 started thread 2 started 0
any appreciated
this called producer-consumer task. can arraylist, it's not right way approach problem.
luckily, java provides collections, blockingqueue collections, designed reason;
//the collection stuff in static blockingqueue<object> items = new blockingqueue<object>(); //(there few different types of blocking queues, check javadocs. //you want linked or array blocking queue //what happens on reader thread public void producer() { //read data collection (all data in file) { //add next item items.put(/* next item file or w/e */); //stop if necessary if (atendoffile) stillreadingdata = false; //etc } }
now need read data out of queue - luckily easy enough;
//what happens on other threads public void consumer() { //keep thread alive long there data process //or long there might more data process while (stillreadingdata || !items.isempty()) { //get next item list //while list empty, sleep "timeout" timeunits, //then while-loop repeat, , on object o = items.poll(long timeout, int units); if (o != null) //process } }
in way, can continuously add items queue producer thread, , items processed consumer thread free (this approach scales lots of consumer threads). if still need collection items, should make second collection , add them after have been processed.
as side note, may still need synchronize oprations occur while processing items. example, need synchronize increments on "weightsum" (or alternately use atomicinteger).
Comments
Post a Comment