Trying to stop all other running threads with CompletableFuture - java

i'm trying to run a for loop on parrallel using 4 threads and I have to stop all other threads when it gets to an else, basically the code looks like this:
CompletableFuture<ResponseEntity<TramRealTimeResponse>> responseEntityCompletableFuture = null;
ExecutorService pool = Executors.newFixedThreadPool(4);
for (TramRulesDTO rule : tramRulesResponse.getPayload()) {
responseEntityCompletableFuture = CompletableFuture.supplyAsync(() ->
{
logger.info("thread " + Thread.currentThread().getName());
TramRule tramRule = TramRuleFactory.getTramRule(rule.getRuleId());
PartnerRuleDto partnerRuleDto = getPartnerRule(partnerRuleResponse.getPayload(), rule.getRuleId());
if (Objects.nonNull(tramRule)) {
try {
tramRule.doTramLogicAndReturnAction(rule, partnerRuleDto,
paymentDetails, intermediaryDetails, partnerRulesConditions, tramRulesRequest);
} catch (TramRealTimeException ex) {
TramRealTimeResponse response = exceptionHandler.handleTramRealTimeException(ex, partnerRuleDto);
if (response.getStatus().equals(200)) {
return null;
} else {
//Stop all threads
return ResponseEntity.ok(response);
}
}
} else {
return null;
}
return null;
}, pool);
}
ResponseEntity<TramRealTimeResponse> tramRealTimeResponseResponseEntity = responseEntityCompletableFuture.get();
Where is the //Stop all threads comment I need somehow to stop all other threads and retrieve the ResponseEntity object down after the for loop. I've tried with executor service shutDown() and shutDownAll() and it doesn't stop anything

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.

Ending console based multi threaded program gracefully

I have the following class, I usually run about 10 threads of it
public class MyClass implements Runnable {
private volatile Device device = null;
public MyClass(Device device) {
this.device = device;
}
#Override
public void run() {
while (true) { // <--- I do know that the "true" has to be changed to a Boolean
try {
Worker worker = new Worker();
worker.work();
System.out.println("Waiting 6 seconds!");
Thread.sleep(6 * 1000);
System.out.println("------------------------------------");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Thread in program ended!");
}
}
and in my main I start the threads like this
for (int i = 0; i < 2; i++) {
(new Thread(new MyClass())).start();
}
This is a console based program. What is the most reliable way to end the program? I think the best way would be to change while (true) to while (Boolean) and somehow change that Boolean for all threads, then when the loop ends, the program will end gracefully.
Here i'm ending it by waiting for a user input but you can change it to fire the stop method from anywhere
public static void main(String[] args) {
List<MyClass> myThreads = new ArrayList<>();
for (int i = 0; i < 2; i++) {
MyClass myClass = new MyClass();
Thread t = new Thread(myClass);
t.start();
myThreads.add(myClass);
}
Scanner in = new Scanner(System.in);
in.next();
for(MyClass t : myThreads){
t.stop();
}
}
class MyClass implements Runnable {
private Boolean flag;
public MyClass() {
this.flag = true;
}
#Override
public void run() {
while (flag) { // <--- I do know that the "true" has to be changed to a Boolean
try {
System.out.println("Waiting 6 seconds!");
Thread.sleep(6 * 1000);
System.out.println("------------------------------------");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Thread in program ended!");
}
public void stop(){
this.flag = false;
} }
The easy way would be to store all your threads in a set and make loop joining them at the end.
Be aware that this is not the most ortodox neither the most efficient way to do this.
In your main:
HashSet<Thread> threads = new HashSet();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new MyClass());
threads.add(t);
t.start();
}
for (Thread thread: threads) {
thread.join();
}
some more material
The following code uses an executor service to fix the number of threads that run at any time, it provides a Future object that also tells you when your thread has shutdown gracefully. They share a shutdown object as well. This offers you a bit more flexibility as the executor service can let you decide how many threads run at any one time gracefully.
First lets created a shared shutdown object that will notify all the threads it is time to shut down. There will be one instance of this and each thread will have a copy.
public static class Shutdown {
private boolean running;
public void shutdown() {
this.running = false;
}
public boolean isRunning() {
return running;
}
}
Next let me just create a dummy thread that does nothing more than sleep forever while it is running. Obviously you can simply replace this with your own thread to do something useful.
public static class MyClass implements Runnable {
final Shutdown shutdown;
public MyClass(Shutdown shutdown) {
this.shutdown = shutdown;
}
#Override
public void run() {
while (shutdown.isRunning()) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
System.out.println("Did not gracefully shut down");
}
}
System.out.println("Thread in program ended!");
}
}
}
Now for the main class which will run everything, this is where the magic happens.
public class Main {
public static void main(String[] args) {
//run exactly 10 threads at a time
ExecutorService executorService = Executors.newFixedThreadPool(10);
//this is how we shut it down
Shutdown globalShutdown = new Shutdown();
//start up the 10 threads
List<Future<?>> futures = new ArrayList<>();
for(int i = 0; i< 10; i++)
futures.add(executorService.submit(new MyClass(globalShutdown)));
//gracefully shut them down
globalShutdown.shutdown();
try {
//wait for them all to shutdown
for(Future<?> future : futures)
future.get();
} catch (InterruptedException e) {
throw new IllegalStateException("This should never happen");
} catch (ExecutionException e) {
throw new IllegalStateException("This should never happen");
}
//everything got shutdown!
}
in practice however you probably also want to handle the case where your thread may not end gracefully due to a bug. Rather than stall forever you might want to add a timeout and if that timeout is exceeded then simply forcibly terminate all remaining threads. To do that replace the above try-catch block with this.
try {
//wait for them all to shutdown
boolean timedout = false;
for(Future<?> future : futures) {
if( !timedout ) {
try {
future.get(30, TimeUnit.SECONDS);
} catch (TimeoutException e) {
timedout = true;
}
}
if(timedout) {
future.cancel(true);
}
}
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException("This should never happen");
}

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.

How does ExecutorService in Java behave if future is inside a loop

I am newb to java execuatorservice.
i went threw some examples in internet but i have some basic doubt.
i created a callable class like below
public class ReadTest implements Callable<String> {
#Override
public String call() throws Exception {
return "OK";
}
}
and i created my main class like below
public class ThreadMain {
public static void main(String args[]) {
try {
ExecutorService execuator = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Future<String> future;
System.out.println("I : " + i);
future = execuator.submit(new ReadTest());
System.out.println(future.get());
future.cancel(true);
}
execuator.shutdownNow();
} catch (Exception ex) {
System.out.println("Error : " + ex);
}
}
}
i am creating FixedThreadPool with limit 5. my loop is running up to 10 times.
1. Here how many threads will be created and used.(according to my view only one thread used, because i cancel with future object every time. is it correct?)
2.i want to execute multiple tasks like above for loop. i have list of commands to execute in shell using jsch. how to do this with threads ?
any help will be appreciated
Are you trying to run async tasks, must do something else while waiting? Maybe this is not what you are looking for but you were studying java executorservice. This app uses async concurrent threads what you were looking for?
public class ThreadMain {
public static void main(String args[]) {
try {
// start async(threaded) workers
ExecutorService execuator = Executors.newFixedThreadPool(5);
List<Future<String>> workers = new ArrayList<Future<String>>();
for (int idx=0; idx < 10; idx++)
workers.add( execuator.submit(new ReadTest()) );
// loop until all workers is done, results may arrive in random order,
// if none is ready then do something else while waiting for next result.
while(!workers.isEmpty()) {
Future<String> worker=null;
for(int idx=0; idx < workers.size(); idx++) {
worker = workers.get(idx);
if (worker.isDone()) {
worker.remove(idx);
break;
}
worker = null;
}
if (worker==null) {
Thread.sleep(500); // do something else, like idle
} else {
System.out.println("Worker is done with results " + worker.get() );
}
}
execuator.shutdown();
} catch (Exception ex) {
System.out.println("Error : " + ex);
}
}
}

Using Executer in a daemon process

We have a daemon process which has to execute everytime and look for the new request to process.Since we have 5 servers where we need to execute the process, current daemon process is creating 5 threads by using newFixedThreadPool of executer service. Once the job is done we are shuttingdown the executer.
When this job deployed in production unix server, after few days of running it hanged.Through the logs we see that all executer threads have finished their job but after executing shutdown it got hanged. I assume in this case,executer has not proprly shut down and since we are checking if it's terminated in a for loop.That loop could be running indefinately and hence no further processing. Please share your thoughts what could be the other reason.
Code:
do {
executor = Executors.newFixedThreadPool(5);
startTime=System.currentTimeMillis();
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i)!='-'||str.charAt(i)!=','||str.charAt(i)!='.'||str.charAt(i)!='|') {
if(str.charAt(i)=='5'||str.charAt(i)=='6'||str.charAt(i)=='7'||str.charAt(i)=='8'||str.charAt(i)=='9') {
String s=str.substring(i, i+1);
Runnable worker = new ExecuteThread(s,batchtype);
executor.execute(worker);
}
}
}
executor.shutdown();
while (!executor.isTerminated()) { }
} while(batchtype == 2);
To resolve this i have included shutdownNow method now and thinking to remove infinite loop where we are checking if the executer is terminated. Please share your views if the below code would be sufficient to curb the error.
do {
executor = Executors.newFixedThreadPool(5);
startTime=System.currentTimeMillis();
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i)!='-'||str.charAt(i)!=','||str.charAt(i)!='.'||str.charAt(i)!='|') {
if(str.charAt(i)=='5'||str.charAt(i)=='6'||str.charAt(i)=='7'||str.charAt(i)=='8'||str.charAt(i)=='9') {
String s=str.substring(i, i+1);
Runnable worker = new ExecuteThread(s,batchtype);
executor.execute(worker);
}
}
}
executor.shutdown();
// FIX
try {
if (!executor.awaitTermination(900,TimeUnit.SECONDS)) {
logger.info("Executor did not terminate in the specified time.");
List<Runnable> droppedTasks = executor.shutdownNow();
if (!executor.awaitTermination(600,TimeUnit.SECONDS)){
logger.info("Even shutdownNow did not terminated in the specified time.");
}
logger.info("Executor abruptly shut down. " + droppedTasks.size() + " tasks will not be executed.");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
logger.error(e.getMessage());
}
//while (!executor.isTerminated()) {
//}
stopTime=System.currentTimeMillis();
logger.info("Time taken by executer to finish job with batchType "+batchtype+ " in sec " +(stopTime-startTime)/1000);
} while(batchtype==2);// to run batch-2 in daemon mode
Execute Thread Code:
public class ExecuteThread extends AbstractMaxisBatchSystem implements Runnable {
private String serverId;
private int batchtype;
public ExecuteThread(String s,int batchtype) throws MaxisBatchFatalException {
this.serverId=s;
this.batchtype=batchtype;
}
private static Logger logger = null;
static{
try{
logger = logger.getLogger(com.maxis.rnb.batch.realReinstatement.FetchNewPayments.ExecuteThread.class);
}
catch(Exception ex) { }
}
/*public ExecuteThread(String s, int batchtype2) throws MaxisBatchFatalException{
// TODO Auto-generated constructor stub
}*/
public void run()
{
try
{
if(batchtype==1)
{
logger.info("FetchNewPayment Batch started for serverID: " +serverId);
FetchNewPayment batch = new FetchNewPayment();
batch.execute(serverId);
}
else if(batchtype==2)
{
//do{
logger.info("ProcessNewPayment Batch started for serverID: " +serverId);
ProcessNewPayment batch = new ProcessNewPayment();
batch.execute(serverId);
//}
//while(true);
}
else if(batchtype==3)
{
logger.info("HouseKeeping Batch started for serverID: " +serverId);
RRHouseKeeping batch = new RRHouseKeeping();
batch.execute(serverId);
}
}
catch (MaxisBatchFatalException e)
{
logger.error("ServerId: "+serverId+":"+e.getMessage(), e);
// System.exit(EXIT_FATAL);
//throw new MaxisBatchFatalException(e.getMessage(), e);
}
}
}

Categories

Resources