This question already has answers here:
How to get the ThreadPoolExecutor to increase threads to max before queueing?
(10 answers)
Closed 5 years ago.
In the ThreadPoolExecutor class, there is a maxPoolSize to specify the maximum thread pool size. That means if number of threads less than that number, threads in the pool should be executed immediately. But I found it is not the case. It cannot go beyond the corePoolSize actually. I am confused. what is the purpose of the maxPoolSize if it does nothing? Here is my testing program:
I have specified the corePoolSize = 2; maxPoolSize = 6; I have created 5 threads (Runnable). I thought all the 5 threads (Runnable) should running simultaneously. But they are not. Only two of them are running, another 3 are put aside until the first two die.
I have read many posts about the topic. But none can guide me to make the 5 threads running simultaneously.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyThreadPoolExecutorTest2
{
private List<MyRunnable> myRunnables = new ArrayList<>();
public static void main(String[] args)
{
new MyThreadPoolExecutorTest2().test();
}
public void test()
{
int poolSize = 2;
int maxPoolSize = 6;
int threadPoolKeepAliveTimeInSec = 30;
ExecutorService threadPoolExecutor =
new MySimpleThreadPoolExecutor(poolSize, maxPoolSize, threadPoolKeepAliveTimeInSec);
int numOfThread = 5;
System.out.println("Start thread pool test with corePoolSize=" + poolSize + ", maxPoolSize=" + maxPoolSize
+ ", actualThreads=" + numOfThread);
for (int i = 0; i < numOfThread; i++)
{
MyRunnable tempRunnable = new MyRunnable(i + 1, "PoolTest" + (i + 1));
myRunnables.add(tempRunnable);
threadPoolExecutor.execute(tempRunnable);
}
System.out.println("********* wait for a while");
try
{
Thread.sleep(20000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("^^^^^^^^^^ shutdown them all");
for (MyRunnable runnable : myRunnables)
{
runnable.shutdown();
}
System.out.println("Ended thread pool test.");
}
public class MyRunnable implements Runnable
{
private int id = 0;
private String name = "";
private boolean shutdown = false;
public MyRunnable(int id, String name)
{
this.id = id;
this.name = name;
}
#Override
public void run()
{
System.out.println("++++ Starting Thread: " + id + ":" + name);
while (!shutdown)
{
try
{
Thread.sleep(200);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println("---- Ended Thread: " + id + ":" + name);
}
public void shutdown()
{
shutdown = true;
}
}
}
class MySimpleThreadPoolExecutor extends ThreadPoolExecutor
{
private static int peakActiveThreads = 0;
private String taskInfo = "";
public MySimpleThreadPoolExecutor(int nThreads, int maxThreads, int threadPoolKeepAliveTimeInSec)
{
super(nThreads, maxThreads, threadPoolKeepAliveTimeInSec * 1000L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
System.out.println("MySimpleThreadPoolExecutor::MySimpleThreadPoolExecutor(), threadPoolSize=" + nThreads
+ ", maxThreadCount=" + maxThreads + ", threadPoolKeepAliveTimeInSec=" + threadPoolKeepAliveTimeInSec);
}
#Override
public void beforeExecute(Thread t, Runnable r)
{
int activeCount = getActiveCount();
if (MySimpleThreadPoolExecutor.peakActiveThreads < activeCount)
{
MySimpleThreadPoolExecutor.peakActiveThreads = activeCount;
}
taskInfo = r.toString();
String msg =
"BeforeE thread(name:id)::" + t.getName() + ":" + t.getId() + ", task::" + r.toString() + "\n"
+ threadPoolInfoStr();
System.out.println("ThreadInfo before, MySimpleThreadPoolExecutor::beforeExecute(), " + msg);
super.beforeExecute(t, r);
}
#Override
public void execute(Runnable command)
{
beforeExecute(Thread.currentThread(), command);
super.execute(command);
}
public String threadPoolInfoStr()
{
return String.format("Thead: %s/%d\n[PoolSize/CorePoolSize] [%d/%d]\nActive: %d\nCompleted: %d\nTask: %d"
+ "\nisShutdown: %s\nisTerminated: %s\npeakActiveThreads: %d\nTaskInfo: %s\nQueueSize: %d", Thread
.currentThread().getName(), Thread.currentThread().getId(), getPoolSize(), getCorePoolSize(),
getActiveCount(), getCompletedTaskCount(), getTaskCount(), isShutdown(), isTerminated(),
MySimpleThreadPoolExecutor.peakActiveThreads, taskInfo, getQueue().size());
}
}
New threads will only be created up to maxPoolSize once the queue is full. Before, the limit is the one defined at corePoolSize.
Reference: http://www.bigsoft.co.uk/blog/index.php/2009/11/27/rules-of-a-threadpoolexecutor-pool-size
More threads are added only if the queue is full.
Since your LinkedBlockingQueue is not bounded, it will never be full. Therefore, there will never be more than the core pool size of threads in the pool.
Use a TransferQueue or use a bounded queue to fix this.
Related
I need the following scenario:
Run all ScheduledFutures within a cycle and call every time the method tasksCompleted() after all tasks finished its execution. The next scheduling cycle must not wait while calling tasksCompleted() after the actual scheduling cycle.
In short: Call a method after the completion of the actual scheduling-cycle and do not stop the next scheduling-cycle
The following code creates tasks and the scheduling works. However, I am not able call tasksCompleted() when all tasks within a cycle completed.
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class Scheduler {
public static void main(String[] args) {
final ScheduledExecutorService ses = Executors.newScheduledThreadPool(10);
System.out.println("- [" + LocalTime.now() + "] run parent-task...");
// create 3 tasks: each task needs 7 seconds.
var tasks = createTasks("child", 3, 7);
List<ScheduledFuture<?>> futures = new ArrayList<>();
tasks.forEach(t ->
{
ScheduledFuture<?> future = ses.scheduleWithFixedDelay(t, 0, 2, TimeUnit.SECONDS);
futures.add(future);
});
// this does not work..
var scheduleCycleCompleted = futures.stream().allMatch(f -> f.isDone());
System.out.println("scheduleCycleCompleted: " + scheduleCycleCompleted);
// maybe a solution with CompletableFuture?
CompletableFuture[] cfs = futures.toArray(new CompletableFuture[futures.size()]);
}
static void tasksCompleted() {
System.out.println("schedule cycle completed");
}
static List<Runnable> createTasks(String group, int numbersOfTasks, long taskDuration) {
var tasks = new ArrayList<Runnable>();
for (var i = 0; i < numbersOfTasks; i++) {
int taskNr = i;
Runnable task = () ->
{
System.out.println("- [" + LocalTime.now() + "] Running " + group + "-task" + taskNr + "...[needs "
+ taskDuration + " seconds]");
try {
TimeUnit.SECONDS.sleep(taskDuration);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
};
tasks.add(task);
}
return tasks;
}
}
Updated
I hope it will work.
CountDownLatch will solve the problem here.
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class Scheduler {
public static void main(String[] args) throws InterruptedException {
final ScheduledExecutorService ses = Executors.newScheduledThreadPool(10);
System.out.println("- [" + LocalTime.now() + "] run parent-task...");
int noOfTask=3;
CountDownLatch countDownLatch = new CountDownLatch(noOfTask);
TaskComplete taskComplete=new TaskCompleteImpl(noOfTask,countDownLatch);
// create 3 tasks: each task needs 7 seconds.
List<Runnable> tasks = createTasks("child", noOfTask, 7,countDownLatch,taskComplete);
List<ScheduledFuture<?>> futures = new ArrayList<>();
tasks.forEach(t ->
{
ScheduledFuture<?> future = ses.scheduleWithFixedDelay(t, 0, 2, TimeUnit.SECONDS);
futures.add(future);
});
// this does not work..
}
interface TaskComplete{
void tasksCompleted();
}
static class TaskCompleteImpl implements TaskComplete {
int totalTask=0;
int index=0;
CountDownLatch countDownLatch;
public TaskCompleteImpl(int totalTask){
}
public TaskCompleteImpl(int noOfTask, CountDownLatch countDownLatch) {
this.totalTask=noOfTask;
this.countDownLatch=countDownLatch;
}
#Override
public synchronized void tasksCompleted() {
index=index+1;
if(index==totalTask){
System.out.println("schedule cycle completed");
index=0;
countDownLatch=new CountDownLatch(totalTask);
}
}
}
static List<Runnable> createTasks(String group, int numbersOfTasks, long taskDuration, CountDownLatch countDownLatch, TaskComplete taskComplete) {
List tasks = new ArrayList<Runnable>();
for (int i = 0; i < numbersOfTasks; i++) {
int taskNr = i;
Runnable task = () ->
{
System.out.println("- [" + LocalTime.now() + "] Running " + group + "-task" + taskNr + "...[needs "
+ taskDuration + " seconds]");
try {
TimeUnit.SECONDS.sleep(taskDuration);
countDownLatch.countDown();
countDownLatch.await();
taskComplete.tasksCompleted();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
};
tasks.add(task);
}
return tasks;
}
}
To handle the case of different runtimes within a scheduling cycle, what you need is a way to identify which task belongs to which group. You can do that by giving them an identifying counter, so that each time a task is executed, the counter is used to denominate the group it's running in.
interface GroupedRunnable extends Runnable {
String getGroup();
}
class CountingRunnable implements GroupedRunnable {
private AtomicInteger counter = new AtomicInteger();
private final Runnable delegate;
private final String taskName;
CountingRunnable(Runnable delegate, String taskName) {
this.delegate = delegate;
this.taskName = taskName;
}
public void run() {
System.out.printf("[%s] - Running task %s in group %s%n", LocalTime.now(), taskName, getGroup());
delegate.run();
counter.incrementAndGet();
System.out.printf("[%s] - Running task %s in group %s finished%n", LocalTime.now(), taskName, getGroup());
}
#Override
public String getGroup() {
return counter.toString();
}
}
Now, you can have a watchdog class that keeps track on which members of which group have already executed. Since you know how many members a group has, a simple counter is sufficient.
class GroupMonitoringService {
// key: group, value: tasks
Map<String, AtomicInteger> finishedTasks = new HashMap<>();
private final Runnable finisher;
private final int groupSize;
GroupMonitoringService(Runnable finisher, int groupSize) {
this.finisher = finisher;
this.groupSize = groupSize;
}
public synchronized void taskFinished(String group) {
var finishedInGroup = finishedTasks.computeIfAbsent(group, k -> new AtomicInteger());
if (finishedInGroup.incrementAndGet() >= groupSize) {
// scheduling group complete
System.out.printf("Group %s finished executing%n", group);
finisher.run();
finishedTasks.remove(group);
}
}
}
Now all you have to do is wrap your original task into a grouped task, and make sure the monitoring service is notified when it's finished, so wrap again.
private static List<Runnable> createTasks() {
List<Runnable> result = new ArrayList<>();
for (int i = 0; i < GROUP_SIZE; i++) {
RandomWaitTask originalTask = new RandomWaitTask();
CountingRunnable groupedTask = new CountingRunnable(originalTask, "Task " + i);
Runnable notifyingRunnable = () -> {
groupedTask.run();
MONITORING_SERVICE.taskFinished(groupedTask.getGroup());
};
result.add(notifyingRunnable);
}
return result;
}
So now you can just schedule those.
You can see the entire code here (although it doesn't actually run properly on that site because of the resource limit it imposes, but if you copy it into your IDE, it works).
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
I'm In a sticky situation. I know this is almost as far as i can get for now, but what i want to do is actually to make an array of thread (or many thread) and accommodate number of threads in queue in the line, so for example i can accommodate 3 thread at a time, i make the first 3 thread run, then make the other wait, when there is free like for example the 1 is free or terminated the other one can start running.
also i want to make sure if the thread can run or not if the thread that is running is the same as the other thread's gender.
Thread myThreads[] = new Thread[LN.GetLine().length()];
int l=LN.GetLine().length();
for (int j = 0; j < LN.GetLine().length(); j++) {
String Name = CR.Gender(LN.GetLine().charAt(j)) + j;
myThreads[j] = new Thread(new MyThread(Name,LN));
myThreads[j].setPriority(l);
System.out.println(myThreads[j].toString());
l--;
}
for(int b=0;b<LN.GetLine().length();b++){
myThreads[b].start();
synchronized(myThreads[b]){
try{
myThreads[b].wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
For now what i can make is accommodate or make 1 thread run at a time.
(Yes this is a Machine bathroom Problem)
My real question is. if i Edit the function run() in myThread() that has a wait() or just plain put a System.out.println(getName() + " is Using");
And how will the thread know in their run() function that other thread is running.
public class MyThread extends Thread {
public MyThread(String id) {
super(id);
}
public void run(){
System.out.println(getName() + " is Using");
>>>Put wait if other thread running<<<<
>>>If can use or not if same gender<<<<
}
Or should i just implement that outside? or put the Waiting outside?
Also i'm really new in Threading so i haven't really explored with Sleep and Interrupt yet.
You can do this without wait.
Here is an example:
public class MyThread extends Thread {
static final Object gender1Lock = new Object();
static final Object gender2Lock = new Object();
int gender;
public MyThread(String id, int gender) {
super(id);
this.gender = gender;
}
public void run(){
System.out.println(getName() + " is waiting");
if(gender == 1){
synchronized(gender1Lock){ // ocupy gender 1
System.out.println(getName() + " is Using");
}
}else if(gender == 2){
synchronized(gender1Lock){ // ocupy gender 2
System.out.println(getName() + " is Using");
}
}
}
}
Since only one thread can synchronize on an object at a time it means that only one thread of a given gender can run at a time. This creates sequential execution of all threads of a given gender.
And here is an example of using this kind of thread.
for(int i = 0; i < 20; i++){
new MyThread("Person " + i, (i%2 == 0) ? 1 : 2).start();
}
... so for example i can accommodate 3 thread at a time, i make the first 3 thread run, then make the other wait, when there is free like for example the 1 is free or terminated the other one can start running.
This can be achieved using a Executor with a fixed Thread Pool.
ExecutorService m = Executors.newFixedThreadPool(3)
ExecutorService f = Executors.newFixedThreadPool(3)
for(;;) {
Object o = new Object();
m.execute(() -> {...; o.wait(); /* You know notify was called on o at this point hence f run clause is running or has just run */ ...})
f.execute(() -> {...; o.notify(); ...})
}
Since this a a batroom the ques are seperate an there will be fixed number of toilets:
ExecutorService m = Executors.newFixedThreadPool(3)
ExecutorService f = Executors.newFixedThreadPool(3)
for(;;) {
Person male = getNextMale();
m.execute(() -> {...; /* do something with male */ ...})
Person female = getNextFemale();
f.execute(() -> {...; /* do something with female */ ...})
}
To implement the queue you can use one of the BlockingQueue implementations.
I would just use two single thread executors obtained via Executors.newSingleThreadExecutor();, one for each gender, and then submit the task to the appropriate executor. Simple and done.
And if you only have one bathroom, then only one executor is needed. For example:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class GetInLine {
public static void main(String[] args) {
List<MyRunnable> myRunnables = new ArrayList<>();
myRunnables.add(new MyRunnable("Bob", false));
myRunnables.add(new MyRunnable("Jill", true));
myRunnables.add(new MyRunnable("Frank", false));
myRunnables.add(new MyRunnable("Amy", true));
myRunnables.add(new MyRunnable("Pete", false));
myRunnables.add(new MyRunnable("Diane", true));
ExecutorService myExecutor = Executors.newSingleThreadExecutor();
for (MyRunnable myRunnable : myRunnables) {
myExecutor.submit(myRunnable);
}
myExecutor.shutdown();
}
}
public class MyRunnable implements Runnable {
private static final int MIN_SLEEP_TIME = 500;
private static final int MAX_SLEEP_TIME = 2000;
private static final int FEMALE_SLEEP_BONUS = 500;
private Random random = new Random();
private String name;
private boolean female;
public MyRunnable(String name, boolean female) {
this.name = name;
this.female = female;
}
public String getName() {
return name;
}
public boolean isFemale() {
return female;
}
#Override
public void run() {
System.out.println(name + " is using");
try {
long sleepTime = MIN_SLEEP_TIME + random.nextInt(MAX_SLEEP_TIME - MIN_SLEEP_TIME);
if (female) {
sleepTime += FEMALE_SLEEP_BONUS;
}
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
System.out.println(name + " is done");
}
}
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
I'm currently developing a programme using multiple producer threads, and one consumer thread. I am wondering if there is an easy way to reference exactly which Producer Thread the Consumer Thread has consumed from.
Here's an example of my output so far:
ConsumerThread consumed: 12 bytes
I would like it to be, for example:
ConsumerThread consumed: 12 bytes from ThreadA
ConsumerThread consumed: 62 bytes from ThreadB
Here is my Consumer Code, called CPU in this case:
class CPU implements Runnable {
private final Vector processingQueue;
private final int SIZE;
public CPU (Vector processingQueue, int size) {
this.processingQueue = processingQueue;
this.SIZE = size;
}
public void run() {
while (true) {
try {
System.out.println("CPU processing: " + consume() + " bytes");
Thread.sleep(50);
} catch (InterruptedException ex) {
Logger.getLogger(CPU.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private int consume() throws InterruptedException {
//wait if queue is empty
while (processingQueue.isEmpty()) {
synchronized (processingQueue) {
System.out.println("Queue is empty " + Thread.currentThread().getName()
+ " is waiting , size: " + processingQueue.size());
processingQueue.wait();
}
}
//Otherwise consume element and notify waiting producer
synchronized (processingQueue) {
processingQueue.notifyAll();
return (Integer) processingQueue.remove(0);
}
}
}
Here's an example of one of my producers, called OperatingSystem:
public class OperatingSystem extends Thread {
private final Vector processingQueue;
private final int SIZE;
public OperatingSystem (Vector processingQueue, int size) {
this.processingQueue = processingQueue;
this.SIZE = size;
}
private void produce(int i) throws InterruptedException {
// suspend producing if queue is full
while (processingQueue.size() == SIZE) {
synchronized (processingQueue) {
System.out.println("Queue is full " + Thread.currentThread().getName()
+ " is waiting , size: " + processingQueue.size());
processingQueue.wait();
}
}
// producing element and notify consumers
synchronized (processingQueue) {
processingQueue.add(i);
processingQueue.notifyAll();
}
}
public void run() {
//OperatingSystem using 300bytes
for (int i = 0; i <= 300; i++) {
System.out.println("Operating System producing: " + i + " bytes");
try {
produce(i);
} catch (InterruptedException ex) {
Logger.getLogger(OperatingSystem.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}//OperatingSystem
Any help would be great, thanks!
Each producer would have to attach its name / identifier to the queue with the actual information (in your case, an int).
class Data {
int data;
String source;
}
And, instead of writing and reading integers from the queue, use Data instances.
You can use setName(String name) from Thread class to identify the producer threads accordingly.