I have a list of 30 servers and I have to make a REST call to each server to get their status. Currently I iterating through list of server and sequentially calling each REST call against each server. So totally it takes around 30 seconds in total to get the response from each server before returning the result to JSP VIEW.
How can we improve this?
One option you could consider is the Java8 streams like:
public void check() {
List<String> endPoints = Arrays.asList("http://www.google.com", "http://www.stackoverflow.com", "inexistent");
{
// this will execute the requests in parallel
List<Boolean> collected = performCheckOverStream(endPoints.parallelStream());
System.out.println(collected);
}
{
// this will execute the requests in serial
List<Boolean> collected = performCheckOverStream(endPoints.stream());
System.out.println(collected);
}
}
private List<Boolean> performCheckOverStream(Stream<String> stream) {
List<Boolean> collected = stream.map(new Function<String, Boolean>() {
#Override
public Boolean apply(String t) {
// do what you need here
}
}).collect(Collectors.toList());
return collected;
}
Using Spring you could either use a #Async annotated method or even use the AsyncRestTemplate, in both cases you will receive a Future<?>. A nice introduction to #Async can be found here and to the AsyncRestTemplate here.
You can do it via ThreaPool like this , with Thread count as your API call count.
public void REST_Thread_executor(int Thread_count, ArrayList URLS) {
ExecutorService executor = Executors.newFixedThreadPool(Thread_count);
for (int i = 0; i < Thread_count; i++) {
String URL = URLS.get(i).toString();
Runnable worker = new MyRunnable(URL);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
}
public String restAPICALL(URL) {
GET or POST or PUT or DELETE
}
public static class MyRunnable implements Runnable {
private final String URL;
RESTThreadExecutor restThreadExecutor = new RESTThreadExecutor();
MyRunnable(String URL) {
this.URL = URL;
}
#Override
public void run() {
restThreadExecutor.restAPICALL(URL);
}
}
You can use the CompletableFuture Interface from java 9. Or the enable on your app the #EnableAsync and on your method use the #Async that will return to you an interface Future.
The both are asynchronous stream.
Related
My code is like:
someFunction() {
// countdownlatch is set up here
for (i = 0; i<cyclesCount; i++) {
//request is sending
someServerRequest.executeWithListener(new CustomListener() {
#Override
public void onComplete(Integer response) {
arraylist.add(response);
}
});
}
//countdownlatch waits here
//do something with arraylist
}
CountDownLatch helps to wait for the loop, but every server request inside it is done in separate thread. So I get responses in random order, which is not suitable for me.
I tried using Phaser and CountDownLatch in different ways, but it didn't work for me.
You could (for example) make a Result class, and add instances of that to an ArrayList. For example:
private static class Result {
private final int resultNumber;
private final Integer response;
private Result(final int resultNumber, final Integer response) {
this.resultNumber = resultNumber;
this.response = response;
}
}
And then have
for (i = 0; i < cyclesCount; i++) {
someServerRequest.executeWithListener(new CustomListener() {
#Override
public void onComplete(Integer response) {
arrayList.add(new Result(i, response));
}
});
}
You can then sort the list based on the resultNumber (and map it to just a list of the responses if you need to), or make Result implements Comparable<Result> and then just use natural sorting from there.
Additionally: ArrayList isn't thread safe (just going by the name of your variable). I'd recommend Collections.synchronizedList(new ArrayList<>()) if you're using this in actual production code.
I'm trying to do multiple heavy calculations using threads.
Then I need to do something with the results after making sure all threads have finished its job.
Here's the basic code:
private class Runner implements Runnable {
private String _result = "fail";
public String get_results() {
return _result;
}
public void run() {
_result = "do complex calculation";
}
}
public void test() {
List<Thread> threads = new ArrayList<Thread>();
List<Runner> threadObjects = new ArrayList<Runner>();
for (int i = 0; i < 10; i++) {
Runner runner = new Runner();
Thread t = new Thread(runner);
t.start();
threads.add(t);
threadObjects.add(runner);
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException ex) {
}
}
for (Runner threadObject : threadObjects) {
System.out.println(threadObject.get_results());
}
}
My question is, is above snippet a common or a good approach to get calculation value?
If not please suggest a better ones.
Also sometimes I got runner.get_results() reponse = "fail", it seems calculation does not processed at all.
Thanks
You can use an ExecutorService such as the ScheduledThreadPoolExecutor;
ExecutorService executor = new ScheduledThreadPoolExecutor(numOfThreads);
With numOfThreads being the number of threads you want sitting in the thread pool.
You can then use the submit(Callable<T> task) method provided by the ScheduledThreadPoolExecutor class to execute the calculation.
You would then have a Callable implementation of your calculation and pass it to the submit() method in ExecutorService to execute the calculation;
class Calculation implements Callable {
#Override
public Object call() throws Exception { // The signature can be changed to return a different type (explained at the end)
return "do complex calculation";
}
}
As we can see from the method signature of the submit(Callable<T> task) method it returns a Future.
public <T> Future<T> submit(Callable<T> task)
The get() method of the Future class will return the result upon successful completion. This would ensure that your calculation completed before reading it.
A further note on the return type of the call() method;
Although this returns Object there is nothing stopping you changing the type of object it returns (this is known as co-variant returns)
For example the following is perfectly legal:
#Override
public String call() throws Exception {
return "do complex calculation";
}
I've been looking for similar questions like these, but for my requirements I think I need something special, I will explain it in detail.
First of all I need to migrate a system which used to work this way:
A class called ServerPool(Thread) initializes with a main class.
This ServerPool creates a queue to receive sockets and a vector to manage worker threads (S.
So in code for pool, I have the following:
public class ServerPool extends Thread {
private LinkedBlockingQueue<SearchQuery> workQueue; //SearchQuery is a Class I defined which can handle two type of processes (for sockets and for single Strings)
private Vector<SearchThread> workers;
private final int NTHREADS = 10;
private int typeOfQuery;
public ServerPool() {
workers = new Vector<SearchThread>(NUM_THREAD);
workQueue = new LinkedBlockingQueue<SearchQuery>();
this.typeOfQuery = typeOfQuery;
SearchThread search = new SearchThread(workQueue);
search.start();
workers.add(search);
}
public void run() {
while(true){
SearchQuery client = null;
if (typeOfQuery == 1) {
client = new SocketQuery(....);
} else if (typeOfQuery == 2) {
client = new StringQuery(...);
}
workQueue.put(client);
}
}
For the SearchThread which executes the process:
public class SearchThread extends Thread {
private LinkedBlockingQueue<SearchQuery> workQueue = null;
private SearchQuery request = null;
public SearchThread(LinkedBlockingQueue<SearchQuery> workSource) {
workQueue = workSource;
}
public void run() {
request = workQueue.take();
//Here I process the request
//And use a PrintWriter to give a "response"
}
}
This used to work using telnet with sockets, but now I've been asked to convert it into a Web Service, so as Web Service it is supposed to return a value, so I think of using Callable, Future and Thread Pools, but I can't replicate exactly the same behavior, I tried implementing this:
public class NewServerPool {
private final int NTHREADS = 10;
private ExecutorService executor;
private LinkedBlockingQueue<SearchQuery> workQueue;
private Vector<Future<String>> futures;
private boolean end = true;
public NewServerPool(int port, SearchQuery typeOfQuery) {
executor = Executors.newFixedThreadPool(NTHREADS);
workQueue = new LinkedBlockingQueue<SearchQuery>();
futures = new Vector<Future<String>>();
}
}
And for the Search Thread that now it is a Callable
public class NewSearchThread implements Callable<String>{
private SearchQuery searchQuery;
public NewSearchThread(SearchQuery searchQuery) {
this.searchQuery = searchQuery;
}
#Override
public String call() throws Exception {
String xmlResponse = null;
if (searchQuery == null) {
throw new InvalidSearchQueryException("The search query is not valid or has null value: " + searchQuery);
}
if (searchQuery instanceof SocketTimed) {
System.out.println("It is socket timed query type");
} else if (searchQuery instanceof WebServiceQuery) {
System.out.println("It is a web service query type");
}
xmlResponse = searchQuery.manageResponse();
return xmlResponse;
}
So I've got stucked in server pool, asumming my WebService will invoke a new instance of Server Pool (NewServerPool) in this case, how could I continue with this? Please I will be really grateful if somebody can help me.
Thanks in advance, best regards.
A couple of things:
First off, your original ServerPool class is flawed, in that it only ever instantiates 1 instance of SearchThread. I think you meant it to start NTHREADS (10) SearchThreads.
Next, it looks like you've changed the approach of NewSearchThread slightly from SearchThread - in that the constructor for NewSearchThread takes a SearchQuery argument, whereas the SearchThread takes a SearchQuery off of the BlockingQueue.
And finally your NewServerPool class differs in its approach from ServerPool, in that ServerPool's run() method continuously places new SearchQuerys into the BlockingQueue. In contrast, NewServerPool's constructor takes a single SearchQuery and does nothing with it.
How about something like this to get you started:
public class NewServerPool extends Thread {
private final int NTHREADS = 10;
private ExecutorService executor;
private Vector<Future<String>> futures;
public NewServerPool(int port, SearchQuery typeOfQuery) {
executor = Executors.newFixedThreadPool(NTHREADS);
futures = new Vector<Future<String>>();
}
public void run() {
while(true){
SearchQuery client = null;
if (typeOfQuery == 1) {
client = new SocketQuery(....);
} else if (typeOfQuery == 2) {
client = new StringQuery(...);
}
futures.add(executor.submit(new NewSearchThread(client)));
}
}
}
Note that I say "to get you started"... as the above still needs some additions such as proper exiting of the run() method when it's time to stop fielding requests (but that's another topic).
If you just want to "launch" the thread pool and return a value, then it doesn't sound like there's any reason to have your NewServerThreadPool extend Thread (but without knowing the full specification of what you are trying to achieve I'm not 100% sure). What type of value is your launch method supposed to return? boolean? String? int? You could instead try something like this:
public class NewServerPool {
private final int NTHREADS = 10;
private ExecutorService executor;
private Vector<Future<String>> futures;
public NewServerPool(int port, SearchQuery typeOfQuery) {
futures = new Vector<Future<String>>();
}
public boolean launchThreadPool() {
executor = Executors.newFixedThreadPool(NTHREADS);
return true;
}
public void submitToThreadPoolForProcessing(SearchQuery client) {
futures.add(executor.submit(new NewSearchThread(client)));
}
public Vector<Future<String>> getFutures() {
return futures;
}
}
Note that in the above, the single-line-contents of the launchThreadPool() method could just as easily be part of the constructor (as it was in the previous post), but breaking it out into its own method allows you to return value "after launching the thread pool. As shown it will return a boolean value (always will return true), but you can of course change the method to return whatever type your specification calls for.
How can i get the variables out of a new thread created with:
public class ParseJson
{
public static String parsejson(String strHttpGet)
{
Thread thread = new Thread(new Runnable()
{
public String run(String strHttpGet)
{
String decodeJson = "someJson";
return decodeJson;
}
});
thread.start();
}
}
I mean how can i get back the decoded json to my function parseJson and give it back to my function call String decodedJson = ParseJson.parseJson(strHttpGet);?
In android, which you have tagged this question as, it would be simpler to use AsyncTask for this situation, because when you override the onPostEXecute method you can put in all sorts of things:
update the UI
send intents and messages
access variables of the parent class if the AsyncTask class is defined inside it.
class MyClass {
Button b;
boolean flag = false;
// Stuff
class MyAsyncClass extends AsyncTask {
// All the stuff, core work in doInBackground
#Override
void onPostExecute(/*vars*/) {
b.setText("Done");
flag = true;
}
}
}
General principles for using AsyncTask: http://developer.android.com/reference/android/os/AsyncTask.html
tutorial: http://samir-mangroliya.blogspot.co.uk/p/android-asynctask-example.html
tutorial: http://androidresearch.wordpress.com/2012/03/17/understanding-asynctask-once-and-forever/
You can't return a value from a Thread in Java. Actually, run() doesn't have a return type.
You could use a shared custom Object that will hold the result. Declare it as final, so you can access it in the anonymous subclass (that would be equivalent to passing a reference to the subclass), and just call a setter on it when the work is done.
public class ParseJson {
public static String parsejson(final String strHttpGet) {
final StringHolder ob = new MyObject();
Thread thread = new Thread() {
public String run() {
String decodeJson = "someJson";
ob.setResult(decodeJson);
}
};
thread.start();
}
private static class StringHolder (){
private String result;
public String getResult() { return result; }
public void setResult(String r) { result = r; }
}
}
I'm not sure I understood why you said get back the decoded json to my function parseJson and give it back to my function call. Do you mean you'll just wait in that function until the Thread is finished? If that's what you want (again, why start a Thread?), you could use Thread.join().
Although if you want to get notified when the Thread finishes, you should indeed look into another option. Neil and Waqas have given good approaches.
You may even use an Observer/Observable pattern for this.
You could use a Future
public class Json {
private static final ExecutorService executor = Executors.newCachedThreadPool();
public static String parse(final String strHttpGet)
throws TimeoutException, InterruptedException, ExecutionException {
Future<String> jsonTask = executor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
String decodeJson = decodeJson(strHttpGet);
return decodeJson;
}
private String decodeJson(String strHttpGet) {
// TODO do actual parsing
return null;
}
});
// Allow the parsing to take one second
return jsonTask.get(1, TimeUnit.SECONDS);
}
}
I'm trying to implement a work queue in Java that limits the amount of work that can be taken at a time. In particular, it is trying to protect access to an external resource. My current approach is to use a Semaphore and a BlockingQueue so that I have something like this:
interface LimitingQueue<V> {
void put(Callable<V> work);
Callable<V> tryPoll();
}
It should behave like this:
#Test
public void workLimit() throws Exception {
final int workQueue = 2;
final LimitingQueue<Void> queue = new LimitingQueue<Void>(workQueue);
queue.put(new Work()); // Work is a Callable<Void> that just returns null.
queue.put(new Work());
// Verify that if we take out one piece of work, we don't get additional work.
Callable<Void> work = queue.tryPoll();
assertNotNull(work, "Queue should return work if none outstanding");
assertNull(queue.tryPoll(), "Queue should not return work if some outstanding");
// But we do after we complete the work.
work.call();
assertNotNull(queue.tryPoll(), "Queue should return work after outstanding work completed");
}
The implementation of tryPoll() uses Semaphore#tryAcquire and, if successful, creates an anonymous Callable that wraps the Semaphore#release call in a try/finally block around the call to work.call().
This works, but is somewhat unsatisfying in that if the user of this class puts work that is of some specific class that implements Callable, the user does not get access to that class back when looking at the result of tryPoll. Notably, tryPoll() returns a Callable<Void>, not a Work.
Is there a way to achieve what the work limitation effect while giving the caller back a usable reference to the work object that was submitted? (It's fine to strengthen the type signature of LimitingQueue to be more like LimitingQueue<R, T extends Callable<R>>.) I can't think of a way to ensure that the semaphore is released after calling the work item without doing this kind of wrapping.
EDIT2 I have replaced what was here with a suggestion on how to implement what you're looking for. Let me know if you want some of the old info back and I can restore it.
public class MyQueue<T> {
private Semaphore semaphore;
public void put(Work<T> w) {
w.setQueue(this);
}
public Work<T> tryPoll() {
return null;
}
public abstract static class Work<T> implements Callable<T> {
private MyQueue<T> queue;
private void setQueue(MyQueue<T> queue) {
if(queue != null) {
throw new IllegalStateException("Cannot add a Work object to multiple Queues!");
}
this.queue = queue;
}
#Override
public final T call() throws Exception {
try {
return callImpl();
} finally {
queue.semaphore.release();
}
}
protected abstract T callImpl() throws Exception;
}
}
Then use it like thus:
public class Test {
public static void main(String[] args) {
MyQueue<Integer> queue = new MyQueue<Integer>();
MyQueue.Work<Integer> work = new MyQueue.Work<Integer>() {
#Override
protected Integer callImpl() {
return 5;
}
};
queue.put(work);
MyQueue.Work<Integer> sameWork = queue.tryPoll();
}
}
Sounds to me like you should just use the builtin ExecutorService. Use Executors#newCachedThreadPool to get a pool, then submit Callable jobs which return back a Future.