java - Executing multiple machines in parallel in thread safe manner -


i have list of hostname executing in parallel using executorservice collect metrics each hostname. , making list has metrics related information hostnames iterating each hostnames future. since executitng multiple hostnames in parallel not sure whether code thread safe or not.

this main code executing multiple hostnames in parallel:

final flows typeofflow = flows.tree;  list<future<machinemetrics>> machinefuturelist = new arraylist<>(); (final string machine : hostnames) {     machinefuturelist.add(executorservice.submit(new callable<machinemetrics>() {         @override         public machinemetrics call() throws exception {             machinemetrics machinemetrics = new machinemetrics();             string url = "http://" + machine + ":8080/text";             map<string, string> metrics = getmetrics(machine, url, typeofflow);             machinemetrics.setmachinename(machine.split("\\.")[0]);             machinemetrics.setdatacenter(testutils.finddatacenter(machine).get().name().tolowercase());             machinemetrics.setmetrics(metrics);             return machinemetrics;         }     })); } list<machinemetrics> metricslist = new arraylist<>(); (future<machinemetrics> future : machinefuturelist) {     try {         metricslist.add(future.get());     } catch (interruptedexception | executionexception ex) {         // log exception here     } } // print hostnames metrics information system.out.println(metricslist); 

and below getmetrics code in same class above code there:

private map<string, string> getmetrics(final string machine, final string url, final flows flowtype) {     map<string, string> holder = new hashmap<string, string>();     try {         resttemplate resttemplate = resttemplateclient.getinstance().getclient();         string response = resttemplate.getforobject(url, string.class);         matcher m = pattern.matcher(response);         while (m.find()) {             string key = m.group(1).trim();             string value = m.group(2).trim();             holder.put(key, value);         }     } catch (exception ex) {         // log here     }      return testutils.process(holder); } 

and below finddatacenter code in testutils class:

public static optional<datacenter> finddatacenter(final string hostname) {     if (!testutils.isempty(hostname)) {         (datacenter dc : dc_list) {             string namepart = "." + dc.name().tolowercase() + ".";             if (hostname.indexof(namepart) >= 0) {                 return optional.of(dc);             }         }     }     return optional.absent(); } 

and below process method in testutils class:

public static map<string, string> process(final map<string, string> holder) {     map<string, string> tempmap = new hashmap<>();      (map.entry<string, string> entry : holder.entryset()) {         if (!entry.getkey().startswith("calls_") && !entry.getvalue().contains("|")) {             continue;         }         string currentkey = entry.getkey();         string currentvalue = entry.getvalue();         stringtokenizer tokenizer = new stringtokenizer(currentvalue, "|");          string count = tokenizer.nexttoken().trim();         string avgdata = tokenizer.nexttoken().trim();         string mediandata = tokenizer.nexttoken().trim();         string n95data = tokenizer.nexttoken().trim();         string n99data = tokenizer.nexttoken().trim();          tempmap.put(generatekey(currentkey, currentkey.contains(miss), count), count);         tempmap.put(generatekey(currentkey, currentkey.contains(miss), avg_in_ms), avgdata);         tempmap.put(generatekey(currentkey, currentkey.contains(miss), median_in_ms), mediandata);         tempmap.put(generatekey(currentkey, currentkey.contains(miss), n95_in_ms), n95data);         tempmap.put(generatekey(currentkey, currentkey.contains(miss), n99_in_ms), n99data);          holder.remove(currentkey);     }      tempmap.putall(holder);      return tempmap; } 

and below generatekey method in testutils class:

private static string generatekey(final string currentkey, final boolean hasmiss, final string constant) {     stringbuilder newkey = new stringbuilder();      if (hasmiss) {         newkey.append(currentkey).append(constant);     } else {         string firstpart = currentkey.substring(0, currentkey.indexof("_"));         string secondpart = currentkey.substring(currentkey.lastindexof("_") + 1, currentkey.length());         newkey.append(firstpart).append(cache).append(secondpart).append(constant);     }      return newkey.tostring(); } 

and below machinemetrics class:

public class machinemetrics {      private string machinename;     private string datacenter;     private map<string, string> metrics;      // normal setters , getters here } 

is above code thread safe? doing wrong may seeing wrong results because of race conditions or thread safety issues?

looks good. methods stateless. use immutable objects methods params. have no problem thread safety.

one remark:

for (future<machinemetrics> future : machinefuturelist) {     try {         metricslist.add(future.get());     } catch (interruptedexception | executionexception ex) {         // log exception here     } } 

get waits if necessary computation complete, , retrieves result. if first call slow, not retrieve other results. use isdone check can call get without waiting.


Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -