java - Thread safe access to arraylist: two producer one consumer. Lock object is enough? -
i have 2 thread can produce value , add in arraylist, , other thread can access read value.
my problem producer can access list in same time consumer use data.
this code :
public class commandtree { lock lock = new reentrantlock(); arraylist<command> cmdtosend = null; jsonobject sendcmdmap; public commandtree(jsonobject sendcmdmap) { this.cmdtosend = new arraylist<command>(); this.sendcmdmap = sendcmdmap; } private synchronized void addmacrocmd(string macro, int fmt, int tgt, int sid,int count,jsonarray sli,string paramname,jsonobject params,int function) { boolean check = false; int = 0; lock.lock(); try { for(i=0; i<cmdtosend.size(); i++) { if(cmdtosend.get(i).getmacroname().equalsignorecase(macro)) { check = true; break; } } if(check == false) { cmdtosend.add(new command(macro,fmt,tgt,sid,count,function,sli)); } if(paramname != null) { if(check) cmdtosend.get(i).setparameter(paramname,params); else cmdtosend.get(cmdtosend.size()-1).setparameter(paramname,params); } } { lock.unlock(); } } private void addparameter(string macro,int fmt, int tgt, int sid,int count,jsonarray sli,string paramname,jsonobject params,int function) { lock.lock(); try { this.addmacrocmd(macro, fmt, tgt, sid, count,sli, paramname,params,function); } { lock.unlock(); } } public int getsize() { return cmdtosend.size(); } public void reset() { lock.lock(); try { cmdtosend.clear(); } { lock.unlock(); } } /* public command getnextcommandinloop() { return cmdtosend.; } */ public command getnextcommand(int i) { command result; lock.lock(); try { result = cmdtosend.get(i); } { lock.unlock(); } return result; } public synchronized boolean populatecommandtree(string i,string target) throws jsonexception { jsonobject tgtcmd = (jsonobject) sendcmdmap.get(target); jsonobject cmdobject; iterator<string> iter = tgtcmd.keys(); while (iter.hasnext()) { string key = iter.next(); if(key.equalsignorecase(i)) { //it general commands jsonobject macro = (jsonobject)tgtcmd.opt(key); cmdobject = (jsonobject) macro.opt("cmd"); addmacrocmd(key,cmdobject.optint("fmt"),cmdobject.optint("tgt"),cmdobject.optint("sid"),cmdobject.optint("count"),cmdobject.optjsonarray("sli"),null,null,macro.optint("function")); return true; } else { //it parameter, have search general command cmdobject = (jsonobject)tgtcmd.opt(key); if(cmdobject == null) { continue; } jsonobject parameter = cmdobject.optjsonobject("parameter"); if( parameter == null) { //there isn't requested command, iterate on next 1 continue; } else { if(((jsonobject) parameter).optjsonobject(i) != null) { jsonobject cmdstructure = (jsonobject)cmdobject.opt("cmd"); //we have found command, save in commandsendcache addmacrocmd(key,cmdstructure.optint("fmt"),cmdstructure.optint("tgt"),cmdstructure.optint("sid"),cmdstructure.optint("count"),cmdstructure.optjsonarray("sli"),i,parameter.optjsonobject(i),cmdobject.optint("function")); return true;//(jsonobject)tgtcmd.opt(key); } else { continue; } } } } return false; }}
i read post on case, don't understand well. thought post code in way can understand in better way.
other problem 1 producer ui thread, , worried if there problem stop ui thread times.
i thought use concurrentlinkedqueue because time need loop on list, , extract value first position, concurrentlinkedqueue don't know how can implementate loop , in way can implementate addmacrocmd method..
in case think use lock object , arraylist.
do have suggestion ? want learn in better way concurrency, not easy me :(
edit : following part of code add , remove command :
public synchronized void readsensordata(string[] sensor, string target) { cmdtree.reset(); for(int i=0;i<sensor.length;i++) { try { cmdtree.populatecommandtree(sensor[i],target); } catch (jsonexception e) { } } writeexecutor.execute(this.writecommandtree); } /** * * @param * @param target * @return * @throws jsonexception when command requested doesn't exists */ private bytearrayoutputstream f = new bytearrayoutputstream(); executorservice writeexecutor = executors.newsinglethreadexecutor(); semaphore mutex = new semaphore(0); volatile boolean diagnostic = false; volatile int index = 0; runnable writecommandtree = new runnable() { @override public void run() { while(index < cmdtree.getsize()) { writecmd(); try { mutex.acquire(); } catch (interruptedexception e) { e.printstacktrace(); } } sendanswerbroadcast("answer", answer); answer = new jsonobject(); index = 0; } };
and mutex release when arrive new response .
addictional information :
the readsensordata() called when button on ux (ui thread) pressed , in same case other thread b. writecommandtree execute in executor (other thread c).
i change name of getnextcommand getcommand - getcommand(int i) called in callback of response (sometime in other thread (i'm forget function ...) , in writecmd inside writecommandtree - getsize in writecommandtree in thread c
don't headaches synchronizing list, use java standard library :
list<command> commands = collections.synchronizedlist(new arraylist<>());
by way, naive implementation of wrap unsafe list , add synchronized
methods.
Comments
Post a Comment