Below is my code:
public class Controller {
public Button button_submitWork;
#FXML
public void handleSubmitWork(ActionEvent event) {
final ExecutorService executorService = Executors.newFixedThreadPool(1, r -> {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
});//set thread daemon, let all threads terminate when the program is closed.
Callable<String> callable = new Callable<String>() {
#Override
public String call() throws Exception {
System.out.println("Executor Service thread");
StringBuilder stringBuilder_output = new StringBuilder();
for (int k = 0; k < 5; k++) {
stringBuilder_output.append(k);
}
//Thread.sleep(1000);
return stringBuilder_output.toString() + "\n";
}
};
Future<String> future = executorService.submit(callable);//Weird line.
//This line must be placed inside the "watchThread" to get the result, but why???
Thread watchThread = new Thread(new Runnable() {
#Override
public void run() {
//<----------Moving to here solve the problem!
System.out.println("Watch thread");
while (!Thread.currentThread().isInterrupted() && !future.isDone()) {
try {
String result = future.get();
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdownNow();
}
}
}
});
watchThread.setDaemon(true);
watchThread.start();
System.out.println("FX thread");
}
}
The question is that the System.out.println(result); inside "watchThread" is never been called. The console output looks like this:
Executor Service thread
FX thread
Watch thread
But when I move the Future<String> future = executorService.submit(callable); to the inside of run method of "watchThread", the output change to:
FX thread
Watch thread
Executor Service thread
01234
which is I expected.
I also discovered that if the call() method has a longer task, say a Thread.sleep(1000), the output change to the result I expected.
So why is that?
The thread you submit to executorService finishes before this line:
while (!Thread.currentThread().isInterrupted() && !future.isDone()) { is called so future.isDone returns true and the while loop is not executed.
If you add Thread.sleep(1000) then it still runs and future.isDone returns false and the while loop executes. The same thing happens when you move Future<String> future = executorService.submit(callable); inside watchThread.
Related
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) {
}
Facing the problem with the ThreadPoolExecutor in Java.
How can I execute a continuous task using it? For example, I want to execute something like this:
#Async
void MyVoid(){
Globals.getInstance().increment();
System.out.println(Thread.currentThread().getName()+" iteration # "+ Globals.getInstance().Iterator);
}
I want it to run forever in 2 parallel asynchronous threads until the user sends a request to stop the ThreadPoolExecutor in the "/stop" controller.
If I use this for example:
#Controller
#RequestMapping("api/test")
public class SendController {
ThreadPoolExecutor executor = new ErrorReportingThreadPoolExecutor(5);
boolean IsRunning = true;
#RequestMapping(value = "/start_new", method = RequestMethod.POST)
public Callable<String> StartNewTask(#RequestBody LaunchSend sendobj) throws IOException, InterruptedException {
Runnable runnable = () -> { MyVoid();};
executor.setCorePoolSize(2);
executor.setMaximumPoolSize(2);
while (IsRunning) {
executor.execute(runnable);
System.out.println("Active threads: " + executor.getActiveCount());
}
return () -> "Callable result";
}
#RequestMapping(value = "/stop", method = RequestMethod.GET)
public Callable<String> StopTasks() {
executor.shutdown(); //for test
if(SecurityContextHolder.getContext().getAuthentication().getName() != null && SecurityContextHolder.getContext().getAuthentication().getName() != "anonymousUser") {
executor.shutdown();
return () -> "Callable result good";
}
else { return () -> "Callable result bad";}
}
}
public class ErrorReportingThreadPoolExecutor extends ThreadPoolExecutor {
public ErrorReportingThreadPoolExecutor(int nThreads) {
super(nThreads, nThreads,
0, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
#Override
protected void afterExecute(Runnable task, Throwable thrown) {
super.afterExecute(task, thrown);
if (thrown != null) {
// an unexpected exception happened inside ThreadPoolExecutor
thrown.printStackTrace();
}
if (task instanceof Future<?>) {
// try getting result
// if an exception happened in the job, it'll be thrown here
try {
Object result = ((Future<?>)task).get();
} catch (CancellationException e) {
// the job get canceled (may happen at any state)
e.printStackTrace();
} catch (ExecutionException e) {
// some uncaught exception happened during execution
e.printStackTrace();
} catch (InterruptedException e) {
// current thread is interrupted
// ignore, just re-throw
Thread.currentThread().interrupt();
}
}
}
}
I'm getting the following errors:
As I understood, a lot of tasks got submitted into the 'executor' queue within a few seconds and then the executor handled all them. (But I need each thread to wait before the current task ends and then submit the new one to the executor, I think.)
HTTP Requests to these controllers are forever "IDLE" until the next request comes, i.e. after sending a request to /api/test/start_new the controller's code executed tasks that are running, but the request is IDLE.
How can I do this in Java?
P.S. Spring MVC is used in the project. It has its own implementation of ThreadPoolExecutor - ThreadPoolTaskExecutor, but I am facing similar problems with it.
I am using single thread executor for long-running threads like this:
executor = Executors.newSingleThreadExecutor(THREAD_FACTORY);
executor.submit(new LongRunnable());
which checks a flag to be stopped:
private class LongRunnable implements Runnable {
#Override
public void run() {
while (isRunning.get()) {
try {
doSomething();
} catch (InterruptedException e) {
...
}
}
}
}
and whole execution is interrupted that way:
#Override
public void close() throws Exception {
isRunning.set(false);
executor.shutdownNow();
}
Still I can see some threads not gc-ed in profiler (while by logs, runnable they were executing has quit outermost while loop).
Question: does provided working with threads strategy memory-leak-free and thread-leak-free?
I am not able to see any issue with executor or shutDownNow. Probably you are looking at different threads in your profiler.
Try this program which is similar to the one in your question and you can see the thread is no longer there after successful shutdown.
public class ExecutorShutdownTest {
private static ExecutorService executor;
private static AtomicLong executorThreadId = new AtomicLong(0);
public static void main(String[] args) {
// get thread MX bean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// create an executor and start the task
executor = Executors.newSingleThreadExecutor(new TestThreadFactory());
LongRunnable runnable = new LongRunnable();
executor.submit(runnable);
// main thread: keep running for sometime
int count = 5;
while (count-- > 0) {
try {
Thread.sleep(1000);
System.out.println(String.valueOf(threadMXBean.getThreadInfo(executorThreadId.longValue())).replace("\r", "").replace(
"\n", ""));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// main thread: stop the task
try {
runnable.close();
System.out.println(String.valueOf(threadMXBean.getThreadInfo(executorThreadId.longValue())).replace("\r", "").replace("\n", ""));
} catch (Exception e) {
e.printStackTrace();
}
// main thread: run some more time to verify the executor thread no longer exists
count = 5;
while (count-- > 0) {
try {
Thread.sleep(1000);
System.out.println(String.valueOf(threadMXBean.getThreadInfo(executorThreadId.longValue())).replace("\r", "").replace("\n", ""));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static class LongRunnable implements Runnable {
private volatile boolean isRunning = true;
#Override
public void run() {
while (isRunning) {
System.out.println("Running");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//ignore
}
}
System.out.println("Stopped");
}
public void close() throws Exception {
System.out.println("Stopping");
isRunning = false;
executor.shutdownNow();
}
}
private static class TestThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
TestThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0) {
#Override protected void finalize() throws Throwable {
super.finalize();
// probably bad idea but lets see if it gets here
System.out.println("Executor thread removed from JVM");
}
};
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
executorThreadId.set(t.getId());
System.out.println("Executor thread created");
return t;
}
}
}
Here's a sample program using the single-thread Executor that manages to strand a thread so that the JVM can't shut down, but it only manages to do it by not calling shutdownNow:
import java.util.concurrent.*;
public class Exec {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new MyTask());
Thread.sleep(20000L);
// executor.shutdownNow();
int retryCount = 4;
while (!executor.isTerminated() && retryCount > 0) {
System.out.println("waiting for tasks to terminate");
Thread.sleep(500L);
retryCount -= 1;
}
}
}
class MyTask implements Runnable {
public void run() {
int count = 0;
try {
while (!Thread.currentThread().isInterrupted() && count < 10) {
Thread.sleep(1000L);
count += 1;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("all done");
}
}
The thread used by the executor has a separate life cycle from the task, this example shows how the task finishes but the thread goes on. Uncommenting the shutdownNow results in the executor's thread terminating. Otherwise the main thread sleeps for a while and exits, leaving the executor's thread hanging out, preventing the JVM from exiting.
My guess is that your close method isn't getting called and your executor never gets shut down. To get more useful answers please add a MVCE so that we can reproduce the problem.
Consider that with interruption there's no need to keep a reference to the Runnable to set the flag. As I read the question the task not finishing is not an issue here, but it would still be better to make the Runnable respond to interruption and lose the flag, just because having less things to keep track of is always an improvement.
I have an executor service that accepts new tasks :
ExecutorService executor = Executors.newFixedThreadPool(1000);
//stupid example with several parralel tasks
for (int i = 0; i < 1000; i++) {
try{
Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
executor.submit(task);
}
catch (ExecutionException e) {
System.out.println(e.getMessage());
}
}
My problem is that I'm not able to catch any exception thrown by the Runnable, unless I'm doing this :
Future<?> future = executor.submit(task);
try {
future.get();
} catch (Exception e) {
System.out.println("############### exception :" + e.getMessage());
}
The problem is that future.get() is blocking, so if I 'm not able to run my tasks asynchronously and my tasks will not run in parallel, but sequentially.
I would like to be able to use Java 8 and CompletableFuture but I can't ...
Do you have any other idea?
Thanks
The code inside the Runnable is executing on a separate thread, so you must handle its exceptions inside the run() method.
If you need to gather all the exceptions for later handling, I would do something like this:
ExecutorService executor = Executors.newFixedThreadPool(1000);
final List<Exception> exceptions = // a place to put exceptions
Collections.synchronizedList(new ArrayList<Exception>());
for (int i = 0; i < 1000; i++) {
Runnable task = new Runnable() {
public void run() {
try {
throw new RuntimeException("foo");
} catch (Exception e) {
exceptions.add(e); // save the exception for later
}
}
};
executor.submit(task);
}
// wait for all the tasks to finish, then...
for (Exception e: exceptions) {
// whatever you want to do
}
Otherwise, if you just want to get information about each exception as it occurs:
Runnable task = new Runnable() {
public void run() {
try {
throw new RuntimeException("foo");
} catch (Exception e) {
e.printStackTrace();
}
}
};
Anything you need to do after the task asynchronously can be added to the task itself.
for (int i = 0; i < 1000; i++) {
final Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
executor.submit(new Runnable() {
public void run() {
try {
task.run();
} catch (Throwable e) {
e.printStackTrace();
}
}
});
}
or you combine them into one Runnable.
This may not be the best solution but we could make a parent Runnable which will do the work of the actual Runnable. The parent will catch all the exceptions you need to know about. Here is slight convoluted approach:
public static void main(String[] args){
ExecutorService executor = Executors.newFixedThreadPool(1000);
//stupid example with several parralel tasks
for (int i = 0; i < 5; i++) {
Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
ParentRunnable t = new ParentRunnable();
t.setRunnable(task, i);
executor.submit(t);
}
}
static class ParentRunnable implements Runnable {
Runnable r;
int index;
public void setRunnable(Runnable r, int index){
this.r = r;
this.index = index;
}
public void run() {
try{
System.out.println("\n" + index + "\n");
r.run();
}catch(Exception e){
e.printStackTrace();
}
}
}
Sorry I have to open a new thread to describe this problem.
This morning I asked this question, there're some replies but my problem is still not solved.
This time I will attach some runnable code(simplified but with the same problem) for you to reproduce the problem:
public class ThreadPoolTest {
public static void main(String[] args) throws Exception {
final ExecutorService taskExecutor = Executors.newFixedThreadPool(5);
Future<Void> futures[] = new Future[5];
for (int i = 0; i < futures.length; ++i)
futures[i] = startTask(taskExecutor);
for (int i = 0; i < futures.length; ++i)
System.out.println("futures[i].cancel(true): " + futures[i].cancel(true));
System.out.println("Cancel DONE.");
taskExecutor.shutdown();
}
private static Future<Void> startTask(final ExecutorService taskExecutor) {
Future<Void> f = taskExecutor.submit(new Callable<Void>() {
public Void call() throws Exception {
try {
downloadFile(new URI("http://stackoverflow.com"));
while(true) {
System.out.println(Thread.currentThread().getName() + ": " + Thread.currentThread().isInterrupted());
if(Thread.currentThread().isInterrupted())
break;
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
});
return f;
}
private static void downloadFile (final URI uri) throws Exception {
// if(true) return;
Socket socket = new Socket (uri.getHost(), uri.getPort() == -1 ? 80 : uri.getPort());
return;
}
}
The code above will most likely be trapped in an infinite loop(you may want to run the code multiple times to witness what I saw), as you can see in the main method I have called futures[i].cancel(true) for all tasks, I don't know why this is happening, this has been torturing me for more than a day.
Your help will be greatly appreciated.
I've played with your code, and noticed that the thread's interrupt status is sometimes true before the socket creation, and false after.
I have tried interrupting a thread and calling the Socket constructor, and the thread always stays interrupted after. I also tried removing the shutdown of the threadpool, and the problem continued to happen.
Then I have tried using 5 different URIs, rather than always the same one. And the problem never happened.
So I wrote this simple program, showing that the thread pool is not the culprit, but the socket is:
public static void main(String[] args) throws Exception {
final URI uri = new URI("http://stackoverflow.com");
for (int i = 0; i < 5; i++) {
Runnable r = new Runnable() {
#Override
public void run() {
Thread.currentThread().interrupt();
System.out.println(Thread.currentThread().isInterrupted());
try {
Socket socket = new Socket (uri.getHost(), uri.getPort() == -1 ? 80 : uri.getPort());
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().isInterrupted());
}
};
new Thread(r).start();
}
}
And indeed, when 5 threads create a socket to the same host and port, 4 of them have their interrupt status cleared.
Then I tried to synchronize the socket creation (on a single lock, but I guess you might use one lock per host/port) :
synchronized(lock) {
try {
Socket socket = new Socket (uri.getHost(), uri.getPort() == -1 ? 80 : uri.getPort());
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
and TADA... the problem disappeared. I would open a bug at Oracle to signal the problem.
I ran your code, and it didn't stop, as you said.
Didn't have much time to investigate why it behaves so, but I found out that declaring the executor service's threads as daemons made the problem go away :
private static ExecutorService TaskExecutor = Executors.newFixedThreadPool(5, new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
I'll come back if I find a better explanation.
I think the problem that task are not started when you try to cancel them. I added Thread.sleep(100) like this:
for (int i = 0; i < futures.length; ++i)
futures[i] = startTask(taskExecutor);
Thread.sleep(100);
for (int i = 0; i < futures.length; ++i)
System.out.println("futures[i].cancel(true): " + futures[i].cancel(true));
and everything was cancelled ok.