Get result immediately when task completed in ThreadPool - java

I refer to this link to create a fixed size threadpool. Then I have a method which allow submit Callable request and get the result, it look like this:
private ExecutorService threadPool = Executors.newFixedThreadPool(5);
private CompletionService<String> pool = new ExecutorCompletionService<String>(threadPool);
public void execute(Callable<String> request){
pool.submit(request);
// what happen if this method is called before get the result???
try {
String result = pool.take().get();
System.out.println("result is " + result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
This execute method can be called many times and the request has difference execute time. The problem is that I want to get the result immediately when it finished. And I want to make sure when executing this method, other calls can be handled and allow add to thread poll.
Here is an example usage:
final Random rnd = new Random();
for (int i = 0; i < 5; i++) {
final String value = String.valueOf(i);
execute(new Callable<String>() {
#Override
public String call() throws Exception {
int sleep = rnd.nextInt(10) * 100;
System.out.println("sleep in " + sleep);
Thread.sleep(sleep);
return value;
}
});
}
And the results are always in order although they have difference execute time:
sleep in 900
result is 0
sleep in 300
result is 1
sleep in 0
result is 2
sleep in 500
result is 3
sleep in 600
result is 4
And I also used the future, but it doesn't work too.
private static void execute(Callable<String> request){
Future<String> future = threadPool.submit(request);
try {
String result = future.get();
System.out.println("result is " + result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Please tell me how can I do that? Thanks in advance.

You aren't using the CompletionService correctly. Your main thread is producing tasks and consuming results. A CompletionService is intended to decouple production and consumption; you'd use it when you have different threads playing these roles. The execute() method makes no sense; it is effectively doing this, but with a lot of obfuscation and overhead:
public void execute(Callable<String> request) {
try {
System.out.println("result is " + request.call());
} catch (Exception ex) {
ex.printStackTrace();
}
}
If you must consume the result as soon as it's ready, you have to make that part of the task. Otherwise, you need one application thread waiting for every task to complete, because if you don't, a task result might be ready and have to wait for a thread to be available to consume it. And if you have one thread per task already, why use a thread pool?
To be more explicit, if you want to guarantee no waiting, you need to do something like this:
final class MyTask implements Callable<Void> {
private final String value;
MyTask(String value) { this.value = value; }
#Override
public Void call() throws InterruptedException {
String result = doWork();
handleResult(result);
return null;
}
private String doWork() throws InterruptedException {
int sleep = ThreadLocalRandom.current().nextInt(10) * 100;
System.out.println("sleep in " + sleep);
Thread.sleep(sleep);
return value;
}
private void handleResult(String result) {
System.out.println("result is " + result);
}
}
If you want to use a CompletionService, you need some separate threads that take() from the service. But in this approach, if tasks are completed faster than they are consumed, some results will wait.

R4j,
the get() waits for the callable to return with the value from call: if you want to submit 5 requests you need to submit all requests and then call get

Related

Executors.newFixedThreadPool How to stop all active threads on synchronized method

I have an executor service that submits x amount of threads concurrently to do a long task. I need to be able to stop all the current threads that are running and prevent queued tasks from starting. I am trying to implement a way to handle stopping threads that are waiting for a synchronized method in which the runnable passes a list of strings back to the interface that called it.
#Override
public synchronized void FilterResults(List<String> Results) {
//System.out.println("Result found: " + Results.size());
try {
Set<String> hs = new HashSet<>();
hs.addAll(Results);
Results.clear();
Results.addAll(hs);
for (String tempURL : Results) {
//System.out.println("Found url: " + tempURL);
if (!isCompleted(tempURL) && !isQueued(tempURL) && !isRunning(tempURL)) {
System.out.println("Added: " + tempURL + " to queue.");
queueLink(tempURL);
startNewThread(tempURL);
}
}
}catch(Exception e) {
}
return;
}
private synchronized void startNewThread(String seedURL) {
if (!isCompleted(seedURL) && !isRunning(seedURL) ) {
if (completedSize("") + runningSize() > 99) {
Stop();
}
String tempProxy = "";
String tempPort = "";
if (UseProxies) {
String Proxy = grabFreeProxy();
String[] splitProxy = Proxy.split(":");
tempProxy = splitProxy[0]; // 004
tempPort = splitProxy[1]; // 034556
}
//System.out.println("Proxy: " + tempProxy);
//System.out.println("Port: " + tempPort);
execService.submit(new Crawl(seedURL, this, tempProxy, tempPort, UseProxies));
removeFromQueue(url);
}
}
#Override
public Collection<String> Stop() {
try {
execService.shutdown();
if (execService.awaitTermination(45, TimeUnit.SECONDS)) {
System.out.println("task completed");
} else {
execService.shutdownNow();
}
} catch (InterruptedException e) {
}
return PROFILES;
}
The Runnable
public class Crawl implements Runnable{
public void run() {
while(!Thread.currentThread().isInterrupted() && shutdown == false) {
try {
//System.out.println(crawler.queueSize());
Thread.sleep(100);
Crawl(url);
}catch (InterruptedException e) {
Thread.currentThread().interrupt(); // set interrupt flag
}
}
public void crawl(){
try {
submitResults(urls); //Calls FilterResults()
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
Thread.currentThread().interrupt();
}
crawler.removeUsedProxy(Proxy + ":" + Port);
this.shutdown();
}
}
When I call my shutdown method it takes 45 seconds+ is there anyway to reliably cancel the task without the long wait? This number grows as I have more threads, and since all the threads are blocking waiting to submit the results, it can take some time. If I cancel the task manually I do not care if the results are stored, I just need to be able to cancel. Any ideas?
Update I've tried ExecutorService#shutdownNow. It has not been reliable
when it comes to killing the tasks that are still blocked on the synchronized method.
Looks like you need to use ExecutorService#shutdownNow in case you don't want to wait and finish all the work and you'll receive a list with the tasks that weren't executed. You may use ExecutionService#awaitTermination (with different parameters than 45 seconds) if you want/need to provide a time to wait for the tasks to finish.

Future is halting rest of program execution

I am trying to execute 2 jobs parallel from main thread but if a callback method take long time to give response rest of requests are pause and wait to complete first.
Here is my code:
private final ExecutorService executorService = Executors.newFixedThreadPool(10);
private void executeService(String uuid) {
System.out.println("query executed done: " + uuid);
}
private String getAsynchTest(final String uuid) throws Exception {
testAsynchF = executorService.submit(
new Callable<String>() {
public String call() throws Exception {
executeService(uuid);
return getFutuerResult(uuid, Thread.currentThread()); // long processing
}
});
return testAsynchF.get();
}
public String getFutuerResult(String uuid, Thread t) {
String dummy = "your result for request: "+uuid;
if (uuid.equalsIgnoreCase("112")) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return dummy;
}
public static void main(String[] args) {
SynchronousTimeoutTester tester = new SynchronousTimeoutTester();
try {
String one = "112"
System.out.println("Result sync call:*** " + tester.getAsynchTest(one));
String two = "115";
System.out.println("Result sync call:**** " + tester.getAsynchTest(two));
} catch (Exception e) {
System.out.println("catched as Exception: " + e);
}
}
Why is this stopping to execute request 115 if request 112 thread is pause?
Since you pass Thread.currentThread() to getFutureResult and that method calls join() on its thread argument (in case uuid is "112"), the method will wait for its own thread to end, which it can't since it's waiting.

java simple thread, but it can't run

it's a simple java thread.
there are 2 threads, and it should be printed every 5 second.
there's no error.
but i just can't run.
please help me finding out what's wrong...
class MyThread extends Thread {
String message;
int delay;
public MyThread(String s, int d) {
message = s;
delay = d;
}
public void run() {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
System.out.println(message + "+" + delay );
}
}
}
public class applet {
public static void main(String[] args){
MyThread mt1, mt2;
mt1 = new MyThread("Hello", 5000);
mt2 = new MyThread("Bye ", 10000);
mt1.start();
mt2.start();
}
}
You are printing ONLY ONCE if an exception occurs...
Modify the run method to:
public void run() {
try {
Thread.sleep(delay);
System.out.println(message + "+" + delay );
} catch (InterruptedException e) {
System.err.println("error here" );
}
}
There are actually 2 mistakes in your program:
1. Print your message in the normal flow
So far you only print your message when you get an InterruptedException which is an exception that is thrown when your thread has been interrupted while sleeping. So instead of printing your message in the catch block, you are supposed to print it after the sleep as next:
try {
Thread.sleep(delay);
System.out.println(message + "+" + delay );
} catch (InterruptedException e) {
// Re-set the interrupted flag
Thread.currentThread().interrupt();
}
2. Add an infinite loop
As you wish to print your message every 5 seconds, you need to call sleep in an infinite loop otherwise your thread will print it only once and die, so the code should be at the end:
try {
while (true) {
Thread.sleep(delay);
System.out.printf("%s+%d%n", message, delay);
}
} catch (InterruptedException e) {
// Re-set the interrupted flag
Thread.currentThread().interrupt();
}
3. Bonus
Alternatively, you can use a ScheduledExecutorService to schedule your tasks with a fixed rate using the method scheduleAtFixedRate, your code would then be:
// Create a ScheduledExecutorService of 2 threads
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
// Schedule my task every 5 seconds starting in 5 seconds
executor.scheduleAtFixedRate(new MyTask("Hello", 5000), 5L, 5L, TimeUnit.SECONDS);
// Schedule my task every 10 seconds starting in 10 seconds
executor.scheduleAtFixedRate(new MyTask("Bye ", 10000), 10L, 10L, TimeUnit.SECONDS);
The class MyTask would simply be:
class MyTask implements Runnable {
String message;
int delay;
public MyTask(String s, int d) {
message = s;
delay = d;
}
public void run() {
System.out.printf("%s+%d%n", message, delay);
}
}

Java 7: How to execute parallel tasks in batches?

I have three web-service calls that can run in parallel. Hence, I'm using a fixed pool of 3 threads to run them.
Now I want to process a couple more web-service calls, that can run in parallel, but only after the first three calls are processed.
How can I batch them? I want the ones inside a batch to run in parallel. And every batch only runs after the previous batch is completed.
So far I am only working with three services. How can I batch them and start using another 2 services?
ExecutorService peopleDataTaskExecutor = Executors.newFixedThreadPool(3);
Future<Collection<PeopleInterface>> task1 = null;
if (condition) {
task1 = peopleDataTaskExecutor.submit(buildTask1Callable(mycontext));
}
Future<Map<String, Task2Response>> task2 = peopleDataTaskExecutor.submit(buildTask2Callable(mycontext));
Future<Map<String, Task3Response>> task3 = null;
task3 = peopleDataTaskExecutor.submit(buildTask3Callable(mycontext));
peopleDataTaskExecutor.shutdown();
try {
peopleDataTaskExecutor.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
}
Collection<PeopleInterface> task1Data = null;
try {
task1Data = task1 != null ? task1.get() : null;
} catch (InterruptedException | ExecutionException e) {
}
Map<String, Task2Response> task2Data = null;
try {
task2Data = task2.get();
} catch (InterruptedException | ExecutionException e) {
}
Map<String, Task3Response> task3Data = null;
if (task3 != null) {
try {
task3Data = task3.get();
} catch (InterruptedException | ExecutionException e) {
}
}
The easiest way to execute batches sequentially is to use the invokeAll() method. It accepts a collection of tasks, submits them to the executor and waits until completion (or until a timeout expires). Here's a simple example that executes three batches sequentially. Each batch contains three tasks running in parallel:
public class Program {
static class Task implements Callable<Integer> {
private static Random rand = new Random();
private final int no;
Task(int no) {
this.no = no;
}
#Override
public Integer call() throws Exception {
Thread.sleep(rand.nextInt(5000));
System.out.println("Task " + no + " finished");
return no;
}
}
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(3);
processBatch(executor, 1);
processBatch(executor, 2);
processBatch(executor, 3);
executor.shutdown();
}
private static void processBatch(ExecutorService executor, int batchNo) throws InterruptedException {
Collection batch = new ArrayList<>();
batch.add(new Task(batchNo * 10 + 1));
batch.add(new Task(batchNo * 10 + 2));
batch.add(new Task(batchNo * 10 + 3));
List<Future> futures = executor.invokeAll(batch);
System.out.println("Batch " + batchNo + " proceseed");
}
}
You can use those Futures in the processBatch() method to check the completion states of the tasks (were they executes successfully or terminated because of an exception), obtain their return values etc.

Setting a maximum execution time for a method/thread

I have a method, which writes to the database. The requirement is to make sure that this method does not execute after a certain time elapses. If it returns before that, then nothing should be done.
The one basic approach that I can think of is doing something like this.
public class LimitedRuntime {
public static void writeToDb(){
// writes to the database
}
public static void main(String[] args) {
long totalExecutionTime = 8000L;
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() - startTime < totalExecutionTime )
{
writeToDb();
}
}
}
One problem with this approach is that even if the method returns before the max total execution time, even then the program halts so as to wait for the time to elapse.
How can I do this better (or maybe more correctly) ? And if we use Thread, how can we find out which Thread executes that method ?
You can do this by sending your job to an executor:
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<?> future = executor.submit(new Runnable() {
#Override
public void run() {
writeToDb(); // <-- your job
}
});
executor.shutdown(); // <-- reject all further submissions
try {
future.get(8, TimeUnit.SECONDS); // <-- wait 8 seconds to finish
} catch (InterruptedException e) { // <-- possible error cases
System.out.println("job was interrupted");
} catch (ExecutionException e) {
System.out.println("caught exception: " + e.getCause());
} catch (TimeoutException e) {
future.cancel(true); // <-- interrupt the job
System.out.println("timeout");
}
// wait all unfinished tasks for 2 sec
if(!executor.awaitTermination(2, TimeUnit.SECONDS)){
// force them to quit by interrupting
executor.shutdownNow();
}
}
There is also an AspectJ solution for that with jcabi-aspects library:
#Timeable(limit = 5, unit = TimeUnit.SECONDS)
public String writeToDb() {
// writeToDb
}
There is an article explaining it further: Limit Java Method Execution Time

Categories

Resources