I am running an infinite loop and need to achieve the following steps:
check available threads in the executor service (the infinite loop)
fetches the task in the loop.
execute the task in the background(non-blocking) and kill the thread executing the task if it takes more than 3 seconds.
I have looked into the future get API that takes a timeout parameter but not this is blocking in nature.
while(any thread available in thread pool){
Task task = fetchTask();
// somehow execute this task in a non-blocking fashion with a timeout.
}
Is there a way to kill the asynchronously executing threads after the timeout?
Will the thread execution will stop and resources will be freed after the timeout?
To achieve this behavior you need this :
Custom class that extends the Thread class and implements the
Runnable interface
A Thread Executor to simply have asynchronous execution of threads
The Custom class let us named it 'Task' can have a special implemetation as follow :
import java.util.Date;
import java.util.concurrent.Callable;
public class Task implements Callable<String> {
private String name;
private Long elapsedTimeInMillSeconds = 0L;
static int counter = 0;
public Task(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
#Override
public String call() throws Exception {
Long startTimeInNanoSeconds, endTimeInNanoSeconds;
startTimeInNanoSeconds = System.nanoTime();
System.out.println("Executing : " + name + ", Current Seconds : " + new Date().getSeconds());
counter++;
System.out.println("Counter = " + counter + " for thread number " + name);
// Check if our logic is working as expected for Task2 we are going to delay for
// 7 seconds
if (counter == 2)
Thread.sleep(7000);
endTimeInNanoSeconds = System.nanoTime();
elapsedTimeInMillSeconds = (endTimeInNanoSeconds - startTimeInNanoSeconds) / 10000;
System.out
.println("Thread [ name : " + name + ", elapsed time : " + this.elapsedTimeInMillSeconds + " Ms ] ");
return "" + this.elapsedTimeInMillSeconds;
}
public synchronized Long getExecutionTime() {
return elapsedTimeInMillSeconds;
}
}
In your Main class try this :
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class Main {
static final int poolSize = 3;
static int counter = 1;
static final ExecutorService executor = Executors.newFixedThreadPool(poolSize);
public static void main(String[] args) {
List<Callable<Task>> callableTasks = new ArrayList<>();
Callable t1 = new Task("Task1");
Callable t2 = new Task("Task2");
Callable t3 = new Task("Task3");
callableTasks.add(t1);
callableTasks.add(t2);
callableTasks.add(t3);
try {
List<Future<Task>> futures = executor.invokeAll(callableTasks, 3, TimeUnit.SECONDS);
futures.stream().forEach(Ft -> {
Ft.cancel(true);
Task task = null;
try {
task = Ft.get();
} catch (Exception e) {
throw new CancellationException("This Thread has been terminated ");
}
});
executor.shutdownNow();
} catch (Exception e) {
if (e instanceof CancellationException) {
System.out.println("Exception : " + e.getMessage());
}
}
}
}
The Thread where the counter == 2 is going to be terminated, be cause of our delay
In a program that tasks are taken from a one file and are executed in parallel i want my program to survive failures / restarts etc. and to resume its execution instead of starting from the beginning each time in case i have a very big list of tasks in the file. What is the proper way of achieving this goal i didn't find much in google to start from. My tasks representation in java are simple pojos with 3 "File" members. Here is my code so far. Thank you for any help in advance.
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class MyTaskManager {
private static AtomicInteger id;
private static String[] in;
private static String cmd;
private static Task task;
private static Process process;
private static MyTaskManager taskManager;
private static Semaphore sem;
private static Map<String, Task> taskMap;
private static StringBuffer sb;
private static List<Runnable> threadList;
public static void main(String[] args) throws IOException {
id = new AtomicInteger();
taskManager = new MyTaskManager();
threadList = new ArrayList<>();
taskMap = new ConcurrentHashMap<>();
sem = new Semaphore(1);
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
// Get task
synchronized (taskManager) {
String line = Files.readAllLines(Paths.get("commands.txt"))
.get(id.get());
id.getAndIncrement();
in = line.split(" ");
cmd = createCmd(cmd);
task = new Task(cmd);
}
// Persist task for later execution if it has missing dependencies
if (!task.checkCondition(task)) {
sem.acquire();
taskMap.put(task.getFile_dep_1().toString().trim(), task);
taskMap.put(task.getFile_dep_2().toString().trim(), task);
sem.release();
// execute the task and see if persisted task can continue his execution
} else if (task.checkCondition(task)) {
sem.acquire();
process = Runtime.getRuntime()
.exec("cmd /c start cmd.exe /k \"" + task.getCmd() + "\"");
process.waitFor();
String taskKey = task.getOutput_file().toString().trim();
System.out.println(taskKey);
if (taskMap.containsKey(taskKey)) {
System.out.println("In contains key " +
Thread.currentThread().getName());
Task taskTmp = taskMap.get(taskKey);
process = Runtime.getRuntime()
.exec("cmd /c start cmd.exe /k \"" + taskTmp.getCmd() + "\"");
process.waitFor();
}
sem.release();
}
} catch (IOException | InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
});
threadList.add(t);
}
BlockingQueue<Runnable> worksQueue = new
ArrayBlockingQueue<>(10);
RejectedExecutionHandler rejectionHandler = new
RejectedExecutionHandlerImpl();
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 20,
TimeUnit.SECONDS, worksQueue, rejectionHandler);
executor.prestartAllCoreThreads();
worksQueue.add(new MultiRunnable(threadList));
executor.shutdown();
}
private static String createCmd(String cmd) {
StringJoiner stringJoiner = new StringJoiner(" ");
stringJoiner.add(in[0]).add(in[1]).add(in[2])
.add(in[3]).add(in[4]);
return stringJoiner.toString();
}
}
class Task {
private File file_dep_1;
private File file_dep_2;
private File output_file;
.......
}
I have one program with strange concurrently bug.
What this program does:
Execute event loop each EVENT_LOOP_PAUSE_DURATION_IN_MS.
For each given task execute processor TaskProcessor
Each 500 ms prints queue size of my executor.
I want to have at most one task in queue per taskId. So, when I add task in queue, I check whether tasks has already existed or not. If there is no task, I add it. In the end of task processing, I remove task from activeTasks map.
If you run the program, then you see the following output:
ERROR: 50
ERROR: 70
ERROR: 80
ERROR: 90
ERROR: 110
ERROR: 120
ERROR: 120
ERROR: 140
So, there is a bug. I don't know why, but size of thread pool queue is infinitely increasing.
You can see, that I remove active tasks in 2 point of program:
In finally block of TaskProcessor, when task has processed.
I remove stale tasks in event loop.
So, if I remove code, which removes tasks at point (2), then the bug disappears. I don't understand this behavior.
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Program {
private static final int NUMBER_OF_TASKS = 40;
private static final int NUMBER_OF_THREADS = 10;
private static final long EVENT_LOOP_PAUSE_DURATION_IN_MS = 40L;
class QueueSizePrinter extends Thread {
private final LinkedBlockingQueue<Runnable> workQueue;
public QueueSizePrinter(LinkedBlockingQueue<Runnable> workQueue) {
this.workQueue = workQueue;
}
#Override
public void run() {
while (true) {
int qSize = workQueue.size();
if (qSize > NUMBER_OF_TASKS) {
System.out.println("ERROR: " + qSize);
}
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class TaskProcessor implements Runnable {
private final String currentTaskId;
private final ConcurrentHashMap<String, Long> activeTasks;
public TaskProcessor(String currentTaskId, ConcurrentHashMap<String, Long> activeTasks) {
this.currentTaskId = currentTaskId;
this.activeTasks = activeTasks;
}
#Override
public void run() {
try {
// emulate of useful work
Thread.sleep(300L);
} catch (Exception e) {
System.out.println("error: " + e.toString());
} finally {
activeTasks.remove(currentTaskId); // (1)
}
}
}
public void program() {
LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
ExecutorService executor = new ThreadPoolExecutor(NUMBER_OF_THREADS, NUMBER_OF_THREADS, 0L, TimeUnit.MILLISECONDS, workQueue);
Set<String> initialTasks = ConcurrentHashMap.newKeySet();
for (int currentTaskIndex = 0; currentTaskIndex < NUMBER_OF_TASKS; currentTaskIndex++) {
initialTasks.add(String.valueOf(currentTaskIndex));
}
new QueueSizePrinter(workQueue).start();
ConcurrentHashMap<String, Long> activeTasks = new ConcurrentHashMap<>();
while (true) {
initialTasks.forEach((currentTaskId) -> {
if (!activeTasks.containsKey(currentTaskId)) {
activeTasks.put(currentTaskId, System.currentTimeMillis());
executor.submit(new TaskProcessor(currentTaskId, activeTasks));
}
});
// (2)
activeTasks.entrySet().removeIf(entry -> {
boolean hasDelete = System.currentTimeMillis() - entry.getValue() > 1000;
if (hasDelete) {
//System.out.println("DELETE id=" + entry.getKey());
}
return hasDelete;
});
try {
Thread.sleep(EVENT_LOOP_PAUSE_DURATION_IN_MS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Program main = new Program();
main.program();
}
}
Problem is at point (2), You are removing stale tasks from activeTasks map. But they are still submitted to ExecutorService. Since You removed it from the map, when while loop execute another cycle, the same task will be resubmitted to ExecutorService. This causes task numbers to increase.
I'm currently working on java application which has a scenario of multiple producers adding tasks to a queue and whenever queue is not empty tasks should be executed at predefined rate. (using multiple threads to maintain execution rate) After executing the available tasks executor has to wait till tasks available in the queue again.
I know blockingQueue can be used to triggering part in here and ScheduledExecutorService for execute tasks at fixed rate. But I could not find a way to link ability of both of this for my need. So I would be very thankful if you could give me any suggestion to make this happen.
You need the task queue to be accessible by both the producer and consumer threads. I've written a basic program to demonstrate this, but I'll let you play around with the BlockingQueue API and the ScheduledExecutor as per your needs:
import java.util.concurrent.*;
public class ProducerConsumer {
private static final BlockingQueue<Integer> taskQueue = new LinkedBlockingQueue<>();
public static void main(String[] args) {
ExecutorService consumers = Executors.newFixedThreadPool(3);
consumers.submit(new Consumer());
consumers.submit(new Consumer());
consumers.submit(new Consumer());
ExecutorService producers = Executors.newFixedThreadPool(2);
producers.submit(new Producer(1));
producers.submit(new Producer(2));
}
private static class Producer implements Runnable {
private final int task;
Producer(int task) {
this.task = task;
}
#Override
public void run() {
System.out.println("Adding task: " + task);
taskQueue.add(task); // put is better, since it will block if queue is full
}
}
private static class Consumer implements Runnable {
#Override
public void run() {
try {
Integer task = taskQueue.take(); // block if there is no task available
System.out.println("Executing task: " + task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
This is the way I could come up with as a solution. It looks little bit rusty but I have tested this and the code is working.
package test;
import java.util.concurrent.*;
public class FixedRateConsumer {
private BlockingQueue<String> queue = new ArrayBlockingQueue<>(20);
private ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(5);
private boolean continueRunning = true;
public void executeInBackGraound() throws InterruptedException, ExecutionException {
while (continueRunning) {
String s = queue.take();
Worker w = new Worker(s);
ScheduledFuture future = executorService.scheduleAtFixedRate(w, 0, 1, TimeUnit.SECONDS);
w.future = future;
try {
if (!future.isDone()) {
future.get();
}
} catch (CancellationException e) {
// Skipping
}
}
}
public void setContinueRunning(boolean state) {
continueRunning = state;
}
public void addConsumableObject(String s) throws InterruptedException {
queue.put(s);
}
private void consumeString(String s) {
System.out.println("Consumed -> " + s + ", ... # -> " + System.currentTimeMillis() + " ms");
}
private class Worker implements Runnable {
String consumableObject;
ScheduledFuture future;
public Worker(String initialConsumableObject) {
this.consumableObject = initialConsumableObject;
}
#Override
public void run() {
try {
if (consumableObject == null) {
consumableObject = queue.take();
}
consumeString(consumableObject);
consumableObject = null;
if (queue.isEmpty()) {
if (future == null) {
while (future == null) {
Thread.sleep(50);
}
}
future.cancel(false);
}
} catch (Exception e) {
System.out.println("Exception : " + e);
}
}
}
}
I have a queue of running threads and would like to expose some of its data while it is executed, to monitor the process.
ThreadPoolExecutor provides access to its queue and I can iterate through these objects to call my overridden toString() method, but these are only threads that are waiting for execution.
Is there a way to access threads that are currently running to call my method? Or maybe there's a better approach for this task in general?
To clarify a bit more about the purpose, here's some code of general idea:
public class GetDataTask implements Runnable {
private String pageNumber;
private int dataBlocksParsed;
private String source;
private String dataType;
public GetDataTask(String source, String dataType) {
this.source = source;
this.dataType = dataType;
}
#Override
public void run() {
//do stuff that affects pageNumber and dataBlocksParsed
}
#Override
public String toString() {
return "GetDataTask{" +
"source=" + source +
", dataType=" + dataType +
", pageNumber=" + pageNumber +
", dataBlocksParsed=" + dataBlocksParsed +
'}';
}
}
and a class holding the executor:
public class DataParseManager {
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 100, 20, TimeUnit.SECONDS, new ArrayBlockingQueue<>(300));
public void addParseDataTask(String source, String dataType) {
executor.execute(new GetDataTask(source, dataType));
}
// here's the method that I need
public String getInfo() {
StringBuilder info = new StringBuilder();
//and here's the method that I'm missing - executor.getActiveThreads()
for (Runnable r : executor.getActiveThreads()) {
info.append(((GetDataTask) r).toString()).append('\n');
}
return info.append(executor.toString()).toString();
}
}
How about wrap Runnable like this.
static class MonitorRunnable implements Runnable {
static final List<Runnable> activeTasks = Collections.synchronizedList(new ArrayList<>());
private final Runnable runnable;
public MonitorRunnable(Runnable runnable) {
this.runnable = runnable;
}
#Override
public void run() {
activeTasks.add(runnable);
runnable.run();
activeTasks.remove(runnable);
}
}
and
public class DataParseManager {
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 100, 20, TimeUnit.SECONDS, new ArrayBlockingQueue<>(300));
public void addParseDataTask(String source, String dataType) {
executor.execute(new MonitorRunnable(new GetDataTask(source, dataType)));
}
// here's the method that I need
public String getInfo() {
StringBuilder info = new StringBuilder();
//and here's the method that I'm missing - executor.getActiveThreads()
synchronized (MonitorRunnable.activeTasks) {
for (Runnable r : MonitorRunnable.activeTasks) {
info.append(((GetDataTask) r).toString()).append('\n');
}
}
return info.append(executor.toString()).toString();
}
}
Whenever you add a thread to the queue, also add it to a second data structure, say a HashSet. Then, if you need to access a running thread, you could check the ExecutorService's queue to find the Threads that are still awaiting execution: every thread in your HashSet that is not still in the ExecutorService's queue is currently running.
Like I wrote in comment. I'd do an active update on a shared statistics object approach:
I'd change the Task like this:
public class GetDataTask implements Runnable {
private String pageNumber;
private int dataBlocksParsed;
private String source;
private String dataType;
HashMap<GetDataTask,String> statistics
public GetDataTask(String source, String dataType, HashMap<GetDataTask,String> statistics) {
this.source = source;
this.dataType = dataType;
this.statistics = statistics;
}
#Override
public void run() {
// you'll probably want to immediately have stats available:
statistics.put(this, this.toString());
//do stuff that affects pageNumber and dataBlocksParsed
// vv this will probably be inside your "do stuff" loop
statistics.put(this, this.toString());
// loop end
// if you do not want stats of finished tasks, remove "this" here.
}
#Override
public String toString() {
return "GetDataTask{" +
"source=" + source +
", dataType=" + dataType +
", pageNumber=" + pageNumber +
", dataBlocksParsed=" + dataBlocksParsed +
'}';
}
}
and the manager:
public class DataParseManager {
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 100, 20, TimeUnit.SECONDS, new ArrayBlockingQueue<>(300));
private HashMap<GetDataTask,String> stats = new ConcurrentHashMap<GetDataTask,String>();
public void addParseDataTask(String source, String dataType) {
executor.execute(new GetDataTask(source, dataType, stats));
}
// here's the method that I need
public String getInfo() {
StringBuilder info = new StringBuilder();
//and here's the method that I'm missing - executor.getActiveThreads()
// >>> iterate "stats"'s values to build the info string ...
return info.append(executor.toString()).toString();
}
}
UPDATE
You can easily change that approach to pulling the info by iterating the Map's keys (which are the executing tasks) and call toString on them. This is quite similar to saka's approach, though. Maybe you feel more comfortable with his.
Since you have control over the used executor, I would use the ThreadPoolExecutor's beforeExecute and afterExecute methods to keep track of running tasks and use that to create a getActiveTasks method.
import java.util.Set;
import java.util.concurrent.*;
public class ActiveTasksThreadPool extends ThreadPoolExecutor {
private final ConcurrentHashMap<Runnable, Boolean> activeTasks = new ConcurrentHashMap<>();
public ActiveTasksThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
#Override
protected void beforeExecute(Thread t, Runnable r) {
activeTasks.put(r, Boolean.TRUE);
super.beforeExecute(t, r);
}
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
activeTasks.remove(r);
}
public Set<Runnable> getActiveTasks() {
// the returned set will not throw a ConcurrentModificationException.
return activeTasks.keySet();
}
public static void main(String[] args) {
final int maxTasks = 5;
ActiveTasksThreadPool tp = new ActiveTasksThreadPool(maxTasks, maxTasks, 10, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
try {
System.out.println("Active tasks: " + tp.getActiveTasks());
final CountDownLatch latch = new CountDownLatch(1);
for (int i = 0; i < maxTasks; i ++) {
final int rnumber = i;
tp.execute(new Runnable() {
#Override
public void run() {
try { latch.await(); } catch (Exception e) {
e.printStackTrace();
}
}
#Override
public String toString() {
return "Runnable " + rnumber;
}
});
}
Thread.sleep(100L); // give threads a chance to start
System.out.println("Active tasks: " + tp.getActiveTasks());
latch.countDown();
Thread.sleep(100L); // give threads a chance to finish
System.out.println("Active tasks: " + tp.getActiveTasks());
} catch (Exception e) {
e.printStackTrace();
} finally {
tp.shutdownNow();
}
}
}
You just need to store the references to the running threads somewhere which will be triggered within the ThreadPoolExecutor, adding on top of the other answers, this is an example of a small application which reads Thread states running inside the ThreadPoolExecutor every 1 second until shutdown:
package sample;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
for (int i = 1; i <= 10; i++)
{
Task task = new Task("Task " + i);
executor.execute(task);
}
executor.shutdown();
try {
while (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
System.out.println("Awaiting completion of threads, threads states: " + Task.getThreadsStateCount());
}
} catch (InterruptedException e) {
}
System.out.println("Executor shutdown -> " + executor.isShutdown());
}
}
class Task implements Runnable {
static final List<Thread> activeTasks = Collections.synchronizedList(new ArrayList<>());
static final Random r = new Random();
private String name;
public Task(String name) {
this.name = name;
}
#Override
public void run() {
Thread t = Thread.currentThread();
System.out.println("current thread : " + t.getName() + " group " + t.getThreadGroup() + " state " + t.getState());
activeTasks.add(t);
try {
int tries = 0;
while (tries < 10) {
int randomNum = r.nextInt(10000);
// do some expensive computation
for(int i = 0; i < 4; i++) {
isPrime(r.nextLong());
}
// now sleep
Thread.sleep(randomNum);
tries++;
}
} catch (InterruptedException e) {
}
System.out.println("completed task for thread : " + t.getName() + " group " + t.getThreadGroup() + " state " + t.getState());
}
static boolean isPrime(long n)
{
if (n <= 1)
return false;
if (n <= 3)
return true;
if (n % 2 == 0 || n % 3 == 0)
return false;
for (int i = 5; i * i <= n; i = i + 6)
if (n % i == 0 || n % (i + 2) == 0)
return false;
return true;
}
public static String getThreadsStateCount() {
return "NEW: " + getCountThreadsState(Thread.State.NEW) +
" ,RUNNABLE: " + getCountThreadsState(Thread.State.RUNNABLE) +
" ,WAITING: " + getCountThreadsState(Thread.State.WAITING) +
" ,TIMED_WAITING: " + getCountThreadsState(Thread.State.TIMED_WAITING) +
" ,BLOCKED: " + getCountThreadsState(Thread.State.BLOCKED) +
" ,TERMINATED: " + getCountThreadsState(Thread.State.TERMINATED);
}
public static long getCountThreadsState(Thread.State state) {
return activeTasks.stream().filter(x -> x.getState() == state).count();
}
}
// prints something like:
Awaiting completion of threads, threads states: NEW: 0 ,RUNNABLE: 1
,WAITING: 0 ,TIMED_WAITING: 9 ,BLOCKED: 0 ,TERMINATED: 0