when i call the below method recursively it is getting stucked and not throwing error. not giving any response. thread pool size is 50. when processing 100K records i am facing this issue.
how to solve this?
Thanks in Advance
public void processActivityDeposits(
Activity activity) {
int partitionSize =
environment.getProperty("patition.size", Integer.class, 1000);
List<Long> records =
service.findReadyToProcessRecords(
activity.getActivityId(),
partitionSize);
if (records != null && records.size() > 0) {
try {
int threadPoolSize =
environment.getProperty("thread.pool.size", Integer.class, 10);
ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
for (Long activityId : records) {
executorService.execute(
new ActivityDepositInternalProcessor(
activityId));
}
executorService.shutdown();
try {
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
processActivityDeposits(
activity);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
I would suggest following changes to your code.
a. move the execution service creation and shutdown out of the if block.
b. Do not set the thread pool size more than 5 as you have only one core,
public void processActivityDeposits(
Activity activity) {
int partitionSize =
environment.getProperty("patition.size", Integer.class, 1000);
List<Long> records =
service.findReadyToProcessRecords(
activity.getActivityId(),
partitionSize);
//moved out of if block
int threadPoolSize =
environment.getProperty("thread.pool.size", Integer.class, 10);
ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
if (records != null && records.size() > 0) {
try {
for (Long activityId : records) {
executorService.execute(
new ActivityDepositInternalProcessor(
activityId));
}
processActivityDeposits(
activity);
} catch (Exception exception) {
exception.printStackTrace();
}
}
//moved out of if block
executorService.shutdown();
try {
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Related
My situation
I'm trying to craft a functionality which would execute n (where n >=0) requests to a given endpoint, but I do understand that sometimes that endpoint might not respond due to
500 error or other issue, so I want to repeat my requests to an endpoint (with a
small interval in between [not yet implemented]) till I get a response, or till I get an unknown error which would indicate what I can't repeat, because of other reasons than a crashed server.
So, I've tried to implement this piece of functionality using Executors and concurrency provided by Java 11 and it does not work as I want
I can't resubmit failed tasks till I get all the responses and I don't know why
I have a method
private void DoMyTasks(List<MyRequest> requests) {
final ExecutorService executorService = Executors.newFixedThreadPool(10);
final ExecutorCompletionService<MyReqResDto> completionService =
new ExecutorCompletionService<>(executorService);
for (final MyRequest MyRequest : requests) {
completionService.submit(new MyCallableRequest(webClient, MyRequest));
}
List<MyReqResDto> responses = new ArrayList<>();
for (int i = 0; i < requests.size(); ++i) {
try {
final Future<MyReqResDto> future = completionService.take();
if (future.get().getEx() != null) {
completionService.submit(new MyCallableRequest(webClient, future.get().getMyRequest()));
}
responses.add(future.get());
} catch (ExecutionException | InterruptedException e) {
log.warn("Error"));
} catch (Exception exception) {
log.error("Other error");
} finally {
executorService.shutdown();
try {
if (!executorService.awaitTermination(10, TimeUnit.MINUTES)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
}
}
responses.size();
}
I'm trying to repeat failed tasks with
if (future.get().getEx() != null) {
completionService.submit(new MyCallableRequest(webClient, future.get().getMyRequest()));
}
and yet, at the end of execution I don't get all responses for my requests. What I get is at most 3 to 5 responses when I try executing 10 requests. Why? How to fix it?
My callable class is
public class MyCallableRequest implements Callable<MyReqResDto> {
private final WebClient webClient;
private final MyRequest myRequest;
public MyCallableRequest(WebClient webClient, MyRequest myRequest) {
this.webClient = webClient;
this.myRequest = myRequest;
}
#Override
public MyReqResDto call() throws Exception {
try {
if (new Random().nextInt(10) % 2 == 0) {
throw new TestException();
}
if (new Random().nextInt(10) % 7 == 0) {
throw new RuntimeException();
}
WebClient.UriSpec<WebClient.RequestBodySpec> uriSpec = webClient.post();
WebClient.RequestBodySpec bodySpec = uriSpec.uri(
s -> s.path("/myEndpoint").build());
MyRequestDto myMyRequestDto = new MyRequestDto();
WebClient.RequestHeadersSpec<?> headersSpec =
bodySpec.body(Mono.just(myMyRequestDto), MyRequestDto.class);
ResponseDto responseDto = headersSpec.exchangeToMono(s -> {
if (s.statusCode().equals(HttpStatus.OK)) {
return s.bodyToMono(ResponseDto.class);
} else if (s.statusCode().is1xxInformational()) {
return s.createException().flatMap(Mono::error);
} else if (s.statusCode().is3xxRedirection()) {
return s.createException().flatMap(Mono::error);
} else if (s.statusCode().is4xxClientError()) {
return s.createException().flatMap(Mono::error);
} else if (s.statusCode().is5xxServerError()) {
return s.createException().flatMap(Mono::error);
} else {
return s.createException().flatMap(Mono::error);
}
//return null;
}).block();
return new MyReqResDto(myRequest, responseDto, null);
} catch (Exception exception) {
return new MyReqResDto(myRequest, null, exception);
}
}
}
Update NO. 1
I changed a for loop to a while loop according to a comment provided by
Slaw and an answer provided by erickson. And this solutions works, meaning that
it is hammering an endpoint till all responses are received without
any errors. But I'm still not sure it feels that I'm building a sh**
tower with this solution. Is there any thread related issues that I should be aware while using executor like this?
while (true) {
Future < MyReqResDto > future = null;
try {
future = completionService.take();
if (future.get().getEx() != null /*and check exception if possible to handle, if not break from a loop*/) {
completionService.submit(new MyCallableRequest(webClient, future.get().getRequestCT());
} else {
responseDtos.add(future.get());
}
} catch (ExecutionException | InterruptedException e) {
log.warn("Error while downloading", e.getCause());
// test if I can recover from these exceptions if no
break;
}
}
if (responseDtos.size() == requests.size()) {
executorService.shutdown();
try {
if (!executorService.awaitTermination(10, TimeUnit.MINUTES)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
break;
}
You are shutting down the executor as soon as you get one response. Perhaps a few more have completed in this time, but you are not allowing time for any others to complete.
Your logic here is wrong. The executor should only be shut down when you are sure no more tasks will be submitted; at soonest, that is after the loop responsible for re-submitting failures.
Here is a simplified view of your code to highlight the premature shutdown:
for (int i = 0; i < requests.size(); ++i) {
try {
final Future<MyReqResDto> future = completionService.take();
...
responses.add(future.get());
...
} finally {
executorService.shutdown();
}
}
I want to use snmp method to query some data by mutithread in sometime,if over time,then the task will be cancel,I write the code like this, if there is something wrong with my code(It means that the thread may only do step 1and step 2,but do not do the step 4:close snmp connetction),how to fix ?Can I have the method that is the task is cancel,I can still close the snmp clent at step 4?
public static void main(String[] args) throws InterruptedException {
var pool = new ThreadPoolExecutor(
100, 100, 0L, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(100));
System.out.println("Executing first batch of tasks...");
submitTasks(pool);
System.out.println("Finish first batch of tasks...");
//call submitTasks(pool) many times
...
}
private static void submitTasks(ExecutorService executor) throws InterruptedException {
var tasks = new ArrayList<Callable<String>>(100);
for (int i = 0; i < 100; i++) {
tasks.add(() -> {
try {
//1.create snmp client
//2.query data with udp link
//3.return result
return result;
}catch (Exception ex){
log.error(String.valueOf(ex));
}
} finally {
//4.close snmp
if (snmp != null) {
snmp.close();
}
}
});
}
List<Future<String>> futureList=executor.invokeAll(tasks,1,TimeUnit.SECONDS);
List<String> list=new ArrayList<>();
for (int i = 0; i < futureList.size(); i++) {
Future<String> future = futureList.get(i);
try {
list.add(future.get());
} catch (CancellationException e) {
log.info("timeOut Task:{}", i);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
I have change the code from Alexander Pavlov's example,it seems that if the task is cancel,the finally code will never run.
public static void main(String[] args) throws InterruptedException {
var pool = new ThreadPoolExecutor(
3, 3, 0L, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(1));
try {
System.out.println("Executing first batch of tasks...");
submitTasks(pool);
System.out.println("Executing second batch of tasks...");
} finally {
pool.shutdown();
}
}
private static void submitTasks(ExecutorService executor) throws InterruptedException {
var tasks = new ArrayList<Callable<String>>(3);
final var latch = new CountDownLatch(3);
log.info(String.valueOf(latch.getCount()));
for (int i = 0; i < 3; i++) {
tasks.add(() -> {
try {
String s="1";
log.info("this.name:"+Thread.currentThread().getName());
for(int a=0;a<1000000L;a++) {
s=a+"";
}
return s;
}catch (Exception ex){
log.error(String.valueOf(ex));
}finally {
latch.countDown();
}
return null;
});
}
List<Future<String>> futureList=executor.invokeAll(tasks,1,TimeUnit.NANOSECONDS);
List<String> list=new ArrayList<>();
//latch.await();//
for (int i = 0; i < futureList.size(); i++) {
Future<String> future = futureList.get(i);
try {
list.add(future.get());
} catch (CancellationException e) {
log.info("timeOut Task:{}", i);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
log.info(String.valueOf(latch.getCount()));
log.info("start to await:");
try {
latch.await(); // WAIT UNTIL ALL TASKS ARE REALLY DONE
} catch (InterruptedException ex) {
log.error(String.valueOf(ex));
}
//never log end to await
log.info("end to await:");
log.info(String.valueOf(latch.getCount()));
}
invokeAll with timeout just calls Thread.interrupt() for running tasks. It does not wait until task stops, it notifies task that interruption is requested. Moreover, some tasks may ignore interruption and continue working. So when you are returning from submitTasks then it does not mean all underlying tasks are really stopped.
If you want to be 100% sure that all tasks are stopped when you exit from submitTasks then use CountDownLatch to control how many tasks have been really finished and exit when running tasks count is zero.
private static void submitTasks(ExecutorService executor) throws InterruptedException {
var c = 100;
final var latch = new CountDownLatch(c); // EXPECT 100 TASKS TO BE COMPLETED
var tasks = new ArrayList<Callable<String>>(c);
for (int i = 0; i < c; i++) {
tasks.add(() -> {
try {
//1.create snmp client
//2.query data with udp link
//3.return result
return result;
} catch (Exception ex) {
log.error(String.valueOf(ex));
} finally {
//4.close snmp
if (snmp != null) {
snmp.close();
}
latch.countDown(); // 1 MORE TASK IS COMPLETED
}
});
}
List<Future<String>> futureList = executor.invokeAll(tasks, 1, TimeUnit.SECONDS);
List<String> list = new ArrayList<>();
for (int i = 0; i < futureList.size(); i++) {
Future<String> future = futureList.get(i);
try {
list.add(future.get());
} catch (CancellationException e) {
log.info("timeOut Task:{}", i);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
try {
latch.await(); // WAIT UNTIL ALL TASKS ARE REALLY DONE
} catch (InterruptedException ex) {
log.error(ex);
}
}
I am trying to call a method multiple times every 60 seconds until a success response from the method which actually calls a rest end point on a different service. As of now I am using do while loop and using
Thread.sleep(60000);
to make the main thread wait 60 seconds which I feel is not the ideal way due to concurrency issues.
I came across the CountDownLatch method using
CountDownLatch latch = new CountDownLatch(1);
boolean processingCompleteWithin60Second = latch.await(60, TimeUnit.SECONDS);
#Override
public void run(){
String processStat = null;
try {
status = getStat(processStatId);
if("SUCCEEDED".equals(processStat))
{
latch.countDown();
}
} catch (Exception e) {
e.printStackTrace();
}
}
I have the run method in a different class which implements runnable. Not able to get this working. Any idea what is wrong?
You could use a CompletableFuture instead of CountDownLatch to return the result:
CompletableFuture<String> future = new CompletableFuture<>();
invokeYourLogicInAnotherThread(future);
String result = future.get(); // this blocks
And in another thread (possibly in a loop):
#Override
public void run() {
String processStat = null;
try {
status = getStat(processStatId);
if("SUCCEEDED".equals(processStat))
{
future.complete(processStat);
}
} catch (Exception e) {
future.completeExceptionally(e);
}
}
future.get() will block until something is submitted via complete() method and return the submitted value, or it will throw the exception supplied via completeExceptionally() wrapped in an ExecutionException.
There is also get() version with timeout limit:
String result = future.get(60, TimeUnit.SECONDS);
Finally got it to work using Executor Framework.
final int[] value = new int[1];
pollExecutor.scheduleWithFixedDelay(new Runnable() {
Map<String, String> statMap = null;
#Override
public void run() {
try {
statMap = coldService.doPoll(id);
} catch (Exception e) {
}
if (statMap != null) {
for (Map.Entry<String, String> entry : statMap
.entrySet()) {
if ("failed".equals(entry.getValue())) {
value[0] = 2;
pollExecutor.shutdown();
}
}
}
}
}, 0, 5, TimeUnit.MINUTES);
try {
pollExecutor.awaitTermination(40, TimeUnit.MINUTES);
} catch (InterruptedException e) {
}
I have a list of threads that need to be executed simultaneously. I was doing this using executorservice initially. The threads that need to be executed are coming from DB and I am retrieving their classnames, storing them in vendorDetails list.
for (Object vendorThread : vendorDetails) {
String thread = (String) vendorThread;
//timeout = details.getTimeout();
Runnable worker = null;
try {
Class c = Class.forName(thread);
Constructor<?> cons = c.getConstructor(SearchRequest.class, Results.class);
worker = (Runnable) cons.newInstance(searchRequest, Results);
} catch (Exception e) {
//e.printStackTrace();
}
if (worker == null) {
System.out.println("------------------------ WORKER IS NULL ---------------");
}
executor.execute(worker);
}
executor.shutdownNow();
try {
if (!executor.isTerminated()) {
executor.awaitTermination(timeout, TimeUnit.SECONDS);
}
} catch (InterruptedException ex) {
//ex.fillInStackTrace();
}
I want to achieve something similar in ejb so I am using ManagedExecutorService.
#EJB
private ThreadName1 threadName1 ;
#EJB
private ThreadName2 threadName2 ;
for (Object vendorThread : vendorDetails) {
System.out.println("in for loop");
String thread = (String) vendorThread;
System.out.println("thread:" + thread);
//timeout = details.getTimeout();
Runnable worker = null;
try {
if (thread.equals("threadName1")) {
System.out.println("in if");
threadName1.setReqRes(SearchRequest, Results);
worker = (Runnable) threadName1;
} else if (thread.equals("threadName2")) {
System.out.println("in spice if");
threadName2.setReqRes(SearchRequest, Results);
worker = (Runnable) threadName2;
}
System.out.println("after if");
} catch (Exception e) {
e.printStackTrace();
}
if (worker == null) {
System.out.println("------------------------ WORKER IS NULL ---------------");
}
System.out.println("before execute");
//managedExecutorService.execute(worker);
managedExecutorService.submit(worker);
System.out.println("after execute");
}
System.out.println("before shutdown");
//managedExecutorService.shutdownNow();
System.out.println("after shutdown");
try {
System.out.println("after shutdown");
/*if (!managedExecutorService.isTerminated()) {
managedExecutorService.awaitTermination(timeout, TimeUnit.SECONDS);
}*/
} catch (InterruptedException ex) {
ex.fillInStackTrace();
// ex.printStackTrace();
}
So ideally I want the threads to run for a stipulated time say 30secs and then return the results of whichever threads have completed their execution.
Now the problem is calling any threadlifecycle methods like shutdown etc throws an exception.
How do I achieve this?
I am using the default ManagedExecutorSerivce.
I dont know if this is the right solution. But I am doing this for now as a workaround. Adding to a Future list all the tasks that are submitted. Then waiting for stipulated time and cancelling all the running tasks. I am sure there is a more elegant solution.
ArrayList<Future> taskList = new ArrayList<>();
for (Object vendorThread : vendorDetails) {
System.out.println("in for loop");
String thread = (String) vendorThread;
System.out.println("thread:" + thread);
//timeout = details.getTimeout();
Runnable worker = null;
try {
if (thread.equals("threadName1")) {
System.out.println("in if");
threadName1.setReqRes(SearchRequest, Results);
worker = (Runnable) threadName1;
} else if (thread.equals("threadName2")) {
System.out.println("in spice if");
threadName2.setReqRes(SearchRequest, Results);
worker = (Runnable) threadName2;
}
System.out.println("after if");
} catch (Exception e) {
e.printStackTrace();
}
if (worker == null) {
System.out.println("------------------------ WORKER IS NULL ---------------");
}
System.out.println("before execute");
//managedExecutorService.execute(worker);
taskList.add(managedExecutorService.submit(worker));;
System.out.println("after execute");
}
System.out.println("before shutdown");
//managedExecutorService.shutdownNow();
System.out.println("after shutdown");
try {
System.out.println("after shutdown");
/*if (!managedExecutorService.isTerminated()) {
managedExecutorService.awaitTermination(timeout, TimeUnit.SECONDS);
}*/
System.out.println("before sleep");
long startTimeLogon = System.currentTimeMillis();
boolean allComplete;
int trueCount = 0;
while (true) {
System.out.println("true count " + trueCount++);
if ((System.currentTimeMillis() - startTimeLogon) >= timeout * 1000) {
break;
}
allComplete = true;
for (Future f : taskList) {
if (!f.isDone()) {
allComplete=false;
}
}
if(allComplete)
break;
Thread.sleep(250);
}
System.out.println("after sleep");
for (Future f : taskList) {
if (!f.isDone()) {
f.cancel(true);
}
}
System.out.println("after cancel");
} catch (InterruptedException ex) {
ex.fillInStackTrace();
// ex.printStackTrace();
}
I am having the code this way..
1) Invoking the updatedb method using reflection...
for (String uniqueSym : activeSymbolsSet) {
futureTaskUtil.submiteTask(new Helper(),
Helper.class.getDeclaredMethod("updateDb",
new Class<?>[] { String.class }), new Object[] { uniqueSym }, 60);
}
- futureTaskUtil:
2) My question is this updatedb is executed as an run time task...
public Object submiteTask(final Object obj, final Method method, final Object[] params, int timeoutSeconds) throws Exception {
if (null != obj && method != null) {
Callable<Object> task = new Callable<Object>() {
public Object call() {
try {
method.setAccessible(true);
Object resultObj = method.invoke(obj, params);
return resultObj;
} catch (Exception e) {
logger.fatal("Exception occured while invoking future task.", e);
}
return null;
}
};
Future<Object> future = executor.submit(task);
try {
Object result = null;
if (timeoutSeconds < 0) {
result = future.get(timoutsec, TimeUnit.SECONDS);
} else {
result = future.get(timeoutSeconds, TimeUnit.SECONDS);
}
logger.info("Result of method execution is :: " + result);
return result;
} catch (TimeoutException e) {
} catch (Exception e) {
logger.fatal("Exception occured while executing future tas : " + obj, e);
} finally {
future.cancel(true); // may or may not desire this
}
}
return null;
}
can some one explain why this is executed as an seperate task and invoking the method?
Future<Object> future = executor.submit(task); This is your culprit You can read about Executer Framework here
What if the method never returns? Then the application would hang at this point.
Using this wrapper, the method will be canceled after 60 seconds.