Task schedule itself inside run() method will cause too many thread created? - java

According to this post:
public class ConditionCheckingTask implements Runnable
{
private final ScheduledExecutorService ses ;
private final Instant whenInstantiated = Instant.now() ;
// Constructor
public ConditionCheckingTask( final ScheduledExecutorService ses ) {
this.ses = ses ;
}
#Override
public void run() {
if( someConditionIsTrue ) {
doSomething ;
} else if ( ChronoUnit.MINUTES.between( this.whenInstantiated , Instant.now() ) > 100000 ) {
// We have exceeded our time limit, so let this task die.
return ;
} else { // Else wait a minute to check condition again.
this.ses.schedule( this , 1 , TimeUnit.MINUTES ) ;
}
}
}
The task schedule itself inside run() method. Suppose the time limit is 100000, then 100000 threads will be created? Since each schedule call will need a separate thread to run, right?

each schedule call will need a separate thread to run, right?
Probably not.
All we know from the code that you showed is that ses refers to a ScheduledExecutorService, and since that's only an interface, we don't actually know what it will do; but any practical implementation of that interface most likely will be some kind of thread pool.
A simple thread pool has a blocking queue of tasks, and a small number of worker threads that each sit in a loop awaiting tasks and performing them;
while (true) {
Runnable task = queue.take();
task.run();
}
In this way, the number of threads used can be much smaller than the number of tasks that are submitted to the queue.
A ScheduledExecutorService such as ScheduledThreadPoolExecutor works in pretty much the same way, except that the queue is some kind of priority queue. A priority queue returns the tasks in the order in which they are scheduled to run instead of returning them in the same order as they were submitted. Each worker loops, waiting until a task at the head of the queue is due, and then it take()s the task, runs it, and goes back to await the next task, same as in the simple thread pool.

Related

ThreadPoolTaskExecutor should Finish Task Queue before Main thread ends

Problem statement:
I have 1,000 tasks and need to process them via ThreadPoolTaskExecutor. ThreadPoolTaskExecutor has corePoolSize = 5, maxPoolSize = 10 and queueCapacity = 1000.
Now from the main method, I am executing the following code
CountDownLatch latch = new CountDownLatch(5);
Collection<Future<?>> futures = new LinkedList<Future<?>>();
for (Map.Entry<String,Boolean> entry : map.entrySet()){
FutureTask task = new FutureTask(new CustomTask(entry));
executor.execute(task);
}
log.info("ACTIVE COUNT : "+executor.getActiveCount());
log.info("SIZE of the QUEUE : "+executor.getThreadPoolExecutor().getQueue().size());
log.info("LATCH WAIT : "+latch.getCount());
latch.wait();
.....
#Override
public Object call() throws Exception {
latch.countDown();
//some logic
return entry;
}
Now, the map has 1,000 entries in it and I want to process all tasks in queue(1,000) and then print these log lines. Whats happening here is, the corePoolSize(which is equal to the CountDounLatch count) create this number of thread and executes them 'Right-Away'. However, when this number is hit, it starts filling up the queue(which is totally fine and desired). However, this queue tasks are processed ONLY AFTER the main thread reaches the end, only then these tasks start executing. This is something that I don't want. I want the Executor to start picking up items from queue as soon as threads get free from processing batch-1.
But in my case, once the batch-1 is processed, the next task is picked only when the main threads ends(which I do not want).
Anyone with a solution on how can this be achieved? (The processing of queue as soon as the thread is available for processing)
P.S : I do understand that latch.await() waits for the threads to complete their execution, but I am looking for a behavior in which it should wait for all the threads to be finished(which is happening) and all the queue should be empty(my expectations).
Thank You
If you are going to do it this way, you need to initialize the latch with the number of tasks that you are going to submit; i.e. 1,000. Also you should decrement the latch at the end of each task, not at its start (as your code currently seems to be doing.)
But you don't need a latch or a counter or anything to implement this. Instead, if you are using a Java SE ExecutorService directly, just do this:
public static void main(String[] args) {
// Submit lots of tasks
executorService.shutdown();
try {
// Waits until all tasks in the queue have completed
executorService.awaitTermination(1_000_000, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
// OK ... will end now
}
}
And if you are using the SpringFramework specific ThreadPoolTaskExecutor class:
public static void main(String[] args) {
// Submit lots of tasks
executor.setAwaitTerminationSeconds(1_000_000);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.shutdown();
}

How to prevent to execute tasks which are waiting in executor queue for free thread

I got many operations to do on multiple threads.
It should be allowed to pause calculations and increase/decrease thread amount then unpause calculations.
At this moment I can just increase amount of threads - tasks already produced by Future and waiting in queue are processed all time and according to docs threads cannot be reduced:
public void setCorePoolSize(int corePoolSize)
Sets the core number of threads. This overrides any value set in the
constructor. If the new value is smaller than the current value,
excess existing threads will be terminated when they next become idle.
If larger, new threads will, if needed, be started to execute any
queued tasks.
So my main problem is:
How to pause executor to not execute tasks waiting in queue?
Class example definition:
import java.util.concurrent.*;
public class Calc {
private int numberOfThreads;
private ThradPoolExecutor pool;
private Future fut;
public void setNumberOfThreads(int threads) {
this.numberOfThreads = threads + 1;
}
public void start() {
if(es == null){
pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(numberOfThreads);
} else {
pool.setCorePoolSize(numberOfThreads);
pool.setMaximumPoolSize(numberOfThreads);
}
fut = pool.submit(() -> {
while (true) {
pool.execute(this::calculate);
}
});
}
public void suspendCalculations() {
fut.cancel(true);
}
public void continueCalculations() {
start();
}
private void calculate() {
// calculation logic, not important
}
}
Basing on my example lets imagine situation:
call setNumberOfThreads(5)
call start()
fut will create big queue with tasks waiting to be proceded ex random number 10000
call suspendCalculations()
call setNumberOfThreads(2)
call continueCalculations()
In this way threads cannot be reduced - we got 10000 tasks to be proceded in queue so we need to wait when queue will be empty.
I want to wait until 5 tasks on 5 threads will end and tasks from queue (10000) will be not passed to threads until I call continueCalculations.
In this way I can call setCorePoolSize(2) before continueCalculations because threads will be not processing tasks because of suspendCalculations

Executor Service and scheduleWithFixedDelay()

Here is my task. I have a static queue of jobs in a class and a static method that adds jobs to the queue. Have n amount of threads that poll from a queue and perform the pulled job. I need to have the n threads poll simultaneously at an interval. AKA, all 3 should poll every 5 seconds and look for jobs.
I have this:
public class Handler {
private static final Queue<Job> queue = new LinkedList<>();
public static void initialize(int maxThreads) { // maxThreads == 3
ScheduledExecutorService executorService =
Executors.newScheduledThreadPool(maxThreads);
executorService.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
Job job = null;
synchronized(queue) {
if(queue.size() > 0) {
job = queue.poll();
}
}
if(job != null) {
Log.log("start job");
doJob(job);
Log.log("end job");
}
}
}, 15, 5, TimeUnit.SECONDS);
}
}
I get this output when I add 4 tasks:
startjob
endjob
startjob
endjob
startjob
endjob
startjob
endjob
It is obvious that these threads perform that jobs serially, whereas I need them to be done 3 at a time. What am I doing wrong? Thanks!
From the documentation:
If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
So you must schedule three independent tasks to have them run concurrently. Also note that the scheduled executor service is a fixed thread pool, which is not flexible enough for many use cases. A good idiom is to use the scheduled service just to submit tasks to a regular executor service, which may be configured as a resizable thread pool.
You are running ScheduledExecutorService with fixed delay, what means, that your jobs will run one after one. Use fixed thread pool, and submit 3 threads at a time. Here is an explanation with examples
If you declare Job extends Runnable then your code simplifies dramatically:
First declare the Executor somewhere globally accessible:
public static final ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
Then add a job like this:
executor.submit(new Job());
You are done.

Terminating all child threads on closing the stage/window

I have multiple instances of child threads which are started and should continue to execute in till the applications exits.
I have classes which extends Task and I create the threads as
new Thread(object of the class).start();
All the threads should be terminated on closing of the primary stage.
primaryStage.onCloseOperation(){...}
I'd manage your threads explicitly from the beginning. In particular, have a thread pool in your parent class like so:
ExecutionService exec = Executors.newCachedExecutionService();
then, if your tasks are meant to keep running (instead of being periodically scheduled) code your tasks responsive to interruption like so:
while(!Thread.currentThread().isInterrupted()){
do stuff;
}
This will make the task run until interrupted. It is important in this case that you never ignore an InterruptedException, because InterruptedException set isInterrupted to false when they are thrown. Do this when you see an InterruptedException:
}catch(InterruptedException e){
Thread.currentThread().interrupt();
return;
}
Then, you can start your child tasks like so:
for(task : tasks){
exec.execute(task);
}
Now, when your parent task finishes, you can simply call:
exec.shutdownNow();
To stop your child tasks. If your child tasks use Thread.currentThread().isInterrupted(), you must use shutdownNow() (shutdown() only works if you want to wait for tasks to stop by themselves).
You should think of using ThreadGroup to group all the threads and then controlling their behavior. Java 5 added the ThreadInfo and ThreadMXBean classes in java.lang.management to get state information.
Here is a sample example to achieve this using tutorial available herehttp://nadeausoftware.com/articles/2008/04/java_tip_how_list_and_find_threads_and_thread_groups:
Getting a list of all threads
Another enumerate( ) method on a ThreadGroup lists that group's threads. With a true second argument, it will recursively traverse the group to fill a given array with Thread objects. Start at the root ThreadGroup and you'll get a list of all threads in the JVM.
The problem here is the same as that for listing thread groups. If the array you pass to enumerate( ) is too small, some threads might be silently dropped from the returned array. So, you'll need to take a guess at the array size, call enumerate( ), check the returned value, and try again if the array filled up. To get a good starting guess, look to the java.lang.management package. The ManagementFactory class there returns a ThreadMXBean who's getThreadCount( ) method returns the total number of threads in the JVM. Of course, this can change a moment later, but it's a good first guess.
Thread[] getAllThreads( ) {
final ThreadGroup root = getRootThreadGroup( );
final ThreadMXBean thbean = ManagementFactory.getThreadMXBean( );
int nAlloc = thbean.getThreadCount( );
int n = 0;
Thread[] threads;
do {
nAlloc *= 2;
threads = new Thread[ nAlloc ];
n = root.enumerate( threads, true );
} while ( n == nAlloc );
return java.util.Arrays.copyOf( threads, n );
}
Create an ExecutorService which has a ThreadFactory to create daemon threads.
For example :
ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
});
and the rest how to use it has already been said by #Enno.
Thanks Enno :)

How to create and process messages from worker threads

How to create asynchronous messages from worker threads to the managing thread. The framework is below. In the snippet, Worker implements Runnable, and threadManager is ExecutorService. The Worker threads are long running, and should pass periodic progress messages up to the manager. One option is to use a blocking queue, but I haven't done that before.
RunnableTester_rev2.threadManager = Executors.newFixedThreadPool( nThreadsAllowed );
final List<Worker> my_tasks = new ArrayList<Worker>();
for ( int i = 0; i < nThreadsToRun; i++ )
{
// The Worker thread is created here.
// Could pass a blocking queue to handle messages.
my_tasks.add( new Worker( ) );
}
final List<Future<?>> fList = new ArrayList<Future<?>>();
for ( final Worker task : my_tasks )
{
fList.add( RunnableTester_rev2.threadManager.submit( task ) );
}
RunnableTester_rev2.threadManager.shutdown();
/**
* Are we all done
*/
boolean isDone = false;
/**
* Number of threads finished
*/
int nThreadsFinished = 0;
/**
* Keep processing until all done
*/
while ( !isDone )
{
/*
* Are all threads completed?
*/
isDone = true;
int ii = 0;
nThreadsFinished = 0;
for ( final Future<?> k : fList )
{
if ( !isThreadDoneList.get( ii ) )
{
final boolean isThreadDone = k.isDone();
if ( !isThreadDone )
{
// Reduce printout by removing the following line
// System.out.printf( "%s is not done\n", mywks.get( ii ).getName() );
isDone = false;
}
}
else
{
nThreadsFinished++;
}
ii++;
}
/*
* WOULD LIKE TO PROCESS Worker THREAD MESSAGES HERE
*/
}
That's really complicated. I would have done something like this.
// no need to use a field.
ExecutorService threadManager = Executors.newFixedThreadPool( nThreadsAllowed );
List<Future<Result>> futures = new ArrayList<Future<Result>>();
for ( int i = 0; i < nThreadsToRun; i++ )
// Worker implements Callable<Result>
futures.add(threadManager.submit(new Worker( )));
threadManager.shutdown();
threadManager.awaitTermination(1, TimeUnit.MINUTE);
for(Future<Result> future: futures) {
Result result = future.get();
// do something with the result
}
I'd use a BlockingQueue. You could try something like this:
final BlockingQueue<Message> q = new LinkedBlockingQueue<Message>();
// start all the worker threads,
// making them report progress by adding Messages into the queue
for (...) {
threadManager.submit(new Runnable() {
// initialize the worker
q.offer(new Message("10% completed"));
// do half of the work
q.offer(new Message("50% completed"));
// do the rest of the work
q.offer(new Message("100% completed"));
});
}
// after starting all the workers, call a blocking retrieval method
// on the queue, waiting for the messages
while (!(everything is done)) {
Message m = q.take();
// process the message
}
The idea is that all the worker threads and the main thread share a common blocking queue. The worker threads are the producers, and the main thread is the consumer.
Here I use .offer(...), but you could use .add(...) and you'd get the same in this case. The difference would be that the former would return false if the queue is full, while the latter would throw an exception. It can't happen here, since I've instantiated an unbounded queue (you could obviously get an OutOfMemoryError). If you use .put(...), however, you'd have to deal with an unchecked InterruptedException (which is not useful in this case: it can't get thrown because the queue is never full -- it is unbounded --, so the method will never block).
Obviously, you can improve it by refactoring the calls to q.offer(...) into a reportStatus(...) method, or something like that.
Maybe you want something different than what I proposed above. Maybe you want the main thread to get asynchronous messages only when each worker thread finishes its work.
My solution is similar that the one proposed by Peter Lawrey, the difference being that, with this solution, the managing thread will get notified as soon as any of worker thread finishes (while with Peter's solution, the result from the worker threads will be retrieved in order -- so, if the first worker thread takes forever to run, even if all the other worker threads finish their jobs you won't know it). Depending on what you are doing, you could get increased performance.
Note that with this solution you cannot infer which thread finished its work (to do so, your Worker class would have to have a method like .getJobId() or something like that), while with Peter's solution you will know exactly which thread finished its work (because you are iterating in the futures list in the same order you instantiated and started the Workers).
If this is the case, you can use an ExecutorCompletionService. It encapsulates an ExecutorService and provides a .take() method (blocking retrieval) that will return Futures from the executor service right after they've completed:
ExecutorCompletionService<Worker> ecs = new ExecutorCompletionService(executorService);
// Worker has to be a callable
// Now you submit your tasks to the ecs:
for (...) {
ecs.submit(new Worker(...));
}
// Now you block on .take():
while (!(everything is done)) {
Future<Worker> f = ecs.take();
// f.get(), for example, to check the results
}
The CompletionService guarantees that, once you take a Future, a call to its .get() method will complete immediately: either by returning the result, or by throwing an ExecutionException, encapsulating the exception thrown by the Callable.

Categories

Resources