Thread Scheduling - Run threads in set order - java

I have a set of roughly 20 threads and i want to schedule them so they run in a set order.
Is there a way to do this. I have tried using priority and setting the priority 1-10 but the scheduler still seems to execute threads at its own order. Btw im working in Java
Is there a way to run threads in a set order ?
Thanks
regards
Mike

What you need is an ExecutorService that will run your threads one at a time, namely : newSingleThreadExecutor.
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.submit(job1);
pool.submit(job2);
pool.submit(job3);

Why do you have multiple threads if you want synchronous behaviour in the first place?
If you've acquired multiple Thread objects from "something else" then you can use thread.run() to execute them in the current thread, which will, of course allow you to control the order.

You don't have to run a single threaded version if the jobs can be executed in parallel. Below is an example where you can use eight threads to run your 20 jobs:
public static void main(String[] args) {
final ExecutorService executorService = Executors.newFixedThreadPool(8);
final Queue<Integer> workItems = new ConcurrentLinkedQueue<Integer>();
for (int i = 0; i < 20; i++) {
workItems.add(i);
}
for (int i = 0; i < 20; i++) {
executorService.submit(new Runnable() {
#Override
public void run() {
final Integer workIem = workItems.poll();
// process work item
}
});
}
// await termination of the exec service using shutdown() and awaitTermination()
}
The idea is that you use an auxiliary queue to maintain the items to be processed and rely on the FIFO ordering of the queue to process the items in order and in parallel.

If the threads depend on each other, then one option would be to schedule only the first thread and have it spawn its dependent threads, which can then turn their dependent threads, etc...
You need to understand, however, that even though you may be launching threads in a particular order, as soon as they start they are off of your hands and they will be fighting for resources and the OS will time-slice their executions, which means some may get "ahead" of threads that were launched before. So if you truly need to keep the order, then I would suggest you use only one thread and let it orchestrate the tasks in a synchronized manner.

Related

Is it possible to wait the main thread while all the threads of executor service are processing tasks

I am having a scenario of around inserting millions of data into the back end and currently using executor framework to load this. I will explain my problem in simpler terms.
In the below case, I am having 10 runnable and three threads to execute the same. Consider my runnable is doing an insert operation and it is taking time to complete the task. When I checked ,It is understood that ,if all the threads are busy, the other tasks will go to the queue and once the threads completed the tasks ,it will fetch the tasks from the pool and complete it.
So in this case, object of SampleRunnable 4 to 10 will be created and this will be in the pool.
Problem: Since I need to load millions of tasks,I cannot load all the records in queue which can lead to memory issues. So my question is instead of taking all tasks in the queue ,is it possible to make the main thread waiting until any one of the executor worker threads becomes available.
Following approaches I tried as a work around instead of queuing this much tasks:
Approach 1: Used Array Blocking Queue for executor and gave the size as 5 (for e.g.)
So in this case, when the 9th task comes ,this will throw RejectedExecutionException and in the catch clause,put a sleep for 1 minute and recursively trying the same.This will get picked up on any of the retry when the thread is available.
Approach 2: Used shut down and await termination. i.e. if the task count is 5, i am putting shut down and await termination. In the await Termination 'if' block (executor.awaitTermination(60000,TimeUnit.SECONDS)),I am instantiating the thread pool again.
public class SampleMain {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i=0;i<10;i++){
executorService.execute(new SampleRunnable(i));
}
executor.shutdown();
}
Sounds like the problem is, you want to throttle the main thread, so that it does not get ahead of the workers. If that's the case, then consider explicitly constructing a ThreadPoolExecutor instance instead of calling Executors.newFixedThreadPool().
That class has several different constructors, and most of them allow you to supply your own blocking queue. If you create an ArrayBlockingQueue with a limited size, then every time the queue becomes full, the main thread will be automatically blocked until a worker makes room by taking another task.
final int work_queue_size = 30;
BlockingQueue work_queue = new ArrayBlockingQueue(work_queue_size);
ExecutorService executor = new ThreadPoolExecutor(..., work_queue);
for (int i=0;i<10;i++){
executorService.execute(new SampleRunnable(i));
}
...

Executor Service shutdown

I am using the ExecutorService. I am opening 10 threads for a for-loop. So it opens 10 threads and when does the connection closes here? At executor.shutdown()? If yes, will it closes all 10 threads and open 10 threads again? Is there anything I can follow better coding standards in order to increase the performance here?
ExecutorService executor = Executors.newFixedThreadPool(10);
for(String str : stringList){
for(String str1 : stringList1){
for(String str2 : stringList2){
executor.execute(new Runnable() {
#Override
public void run() {
//do something
}
}
}
}
executor.shutdown();
executor.awaitTermination(24L, TimeUnit.HOURS);
Actually my idea is to iterate through the loop and save the data in a file and save it for every iteration. So I want to follow the best practices here as I don't want to see any server related issues like connection issues/outOfMemory exceptions in later stages. Please suggest.
I have implemented this by myself but I am a noob in multi-threading. So to get some clarification after seeing some other blogs and posts I have posted this. Please help!
Executors.newFixedThreadPool(10) does exactly what it sounds like - it creates a thread pool, with a maximum of 10 threads. From the documentation:
The threads in the pool will exist until it is explicitly shutdown
So, best practice is to share the thread pool where possible. Don't do this:
for (int i = 0; i < 8; i++) {
ExecutorService executor = Executors.newFixedThreadPool(10);
for (String str1 : stringList1) {
for (String str1 : stringList1) {
executor.execute(new Runnable(){
public void run(){ /* Some work... */ }
});
}
}
executor.shutdown();
executor.awaitTermination(24L, TimeUnit.HOURS);
}
Notice that a new FixedThreadPool is created and destroyed 8 times within the for-loop, and creating/destroying the thread pools is creating/destroying up to 10 threads. This is bad, because it defeats the point of using a thread pool. If you're going to use a pool within a loop, make sure you re-use it where you can:
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 8; i++) {
for (String str1 : stringList1) {
for (String str1 : stringList1) {
executor.execute(new Runnable(){
public void run(){ /* Some work... */ }
});
}
}
}
executor.shutdown();
executor.awaitTermination(24L, TimeUnit.HOURS);
And finally, one last thing to watch out for is the amount of work you queue. If you are queueing work faster than the thread pool can process it, then the queue size will slowly grow, until you reach an OutOfMemoryException. Unfortunately, there's no built-in way to check the number of tasks remaining in the thread pool, so you'll have to work that one out on your own.
This concept applies to the server as well - if the number of incoming requests per second is higher than the number of requests the server can process per second, for a long enough duration, then the server will run out of resources and crash. The solution is usually to have automatic scaling and load balancing, and knowing how to configure these things is a very useful skill to have in the industry.
when does the connection closes here? At executor.shutdown()? If yes, will it closes all 10 threads and open 10 threads again?
Once you call ExecutorService.html#shutdown, no new new tasks are submitted to the pool and once no tasks in the pool, ExecutorService will be shutdown.
void shutdown()
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.
Once shutdown is triggered, it won't open 10 threads again unless you re-create ExecutorService
Actually my idea is to iterate through the loop and save the data in a file and save it for every iteration. So I want to follow the best practices here as I don't want to see any server related issues like connection issues/outOfMemory exceptions in later stages
Don't do it. Let's wait for ExecutorService to properly shutdown.
Other way to address your issue : Wait for completion of your tasks. You can find more details in:
How to properly shutdown java ExecutorService
On a different note:
newFixedThreadPool creates unbounded ExecutorService. Look out for other alternatives in:
How to properly use Java Executor?

Quasar Fiber equivalent of Java's ThreadPoolExecutor?

I've been curious about Quasar and its light weight Fibers as a replacement for Threads. After consulting their API docs, I have not been able to figure out how to go about converting a typical ThreadPoolExecutor into a pool of Fibers.
int maxThreadPoolSize = 10;
ThreadPoolExecutor executor = new ThreadPoolExecutor(
maxThreadPoolSize,
maxThreadPoolSize,
10, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(maxThreadPoolSize),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
for (int i = 0; i < 100; i++) {
executor.execute(new Runnable() {
#Override
public void run() {
// run some code
}
});
}
The above code creates a pool with 10 threads, a queue in front of the pool that can hold 10 elements and a rejection policy (when queue is full) to have main thread execute a Runnable task itself. As the for loop creates 100 runnables, they will be executed 10 at a time in the pool, 10 queued up, and main thread picks up a Runnable itself until others are finished, after which main thread goes back to adding Runnables to executor.
How would you do this with Quasar's Fibers? Is it meant to be used as such in the first place?
EDIT: My original question was poorly phrased. Essentially I was trying to find a mechanism to limit how many Fibers can run concurrently. For example, do not launch more Fibers if there is already 200 Fibers running. If max number of Fibers are running, wait until one finishes before launching a new one.
Fibers are very cheap so you shouldn't need pooling (and its async job-dispatching model) at all: just fire up a fiber and let it run regular sequential code every time you need a new sequential process to be run concurrently with others.
Each fiber scheduled by a FiberScheduler, when you create a Fiber without scheduler, a FiberForkJoinScheduler will be created and assigned to this fiber.
In short, if you want to manage your fibers in a thread pool, use FiberExecutorScheduler:
Quasar's document about scheduling fibers
Your code could be like this
int maxThreadPoolSize = 10;
ThreadPoolExecutor executor = new ThreadPoolExecutor(
maxThreadPoolSize,
maxThreadPoolSize,
10, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(maxThreadPoolSize),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
FiberExecutorScheduler scheduler = new FiberExecutorScheduler("FibersInAPool", executor);
for (int i = 0; i < 100; i++) {
Fiber fiber = new Fiber<Void>(scheduler
, new SuspendableCallable<Void>() {
#Override
public Void run() throws SuspendExecution, InterruptedException {
// run some code
return null;
}
});
fiber.start();
}
java.util.concurrent.Semaphore ended up working well in my particular setup.
General gist of my solution:
create Semaphore with desired max number of permits (aka max concurrent Fibers)
main thread is in charge of picking up tasks to process from a queue
main thread calls semaphore.acquire():
if a permit is available, then launch new Fiber to process task
if all permits are taken, then semaphore will block main thread and wait until a permit becomes available
once Fiber is launched, main thread repeats its logic. Picks up a new task from queue and attempts to launch a new Fiber.
Bonus: standard Java's Semaphore is fixed and number of permits can not be dynamically adjusted. To make it dynamic this link came in handy: http://blog.teamlazerbeez.com/2009/04/20/javas-semaphore-resizing/
we just did a pre-release of kilim 2.0. it provides a fiber and actor implementation (similar to quasar) and is backed by ThreadPoolExecutor
the most efficient way to limit the number of concurrent tasks would be to have one task serve as a controller and listen to a mailbox (i think quasar calls these channels) and maintain a count of running tasks. when each task finishes, message the mailbox
generally, it doesn't make sense to use more threads than there are cores

Java Executor with throttling/throughput control

I'm looking for a Java Executor that allows me to specify throttling/throughput/pacing limitations, for example, no more than say 100 tasks can be processed in a second -- if more tasks get submitted they should get queued and executed later. The main purpose of this is to avoid running into limits when hitting foreign APIs or servers.
I'm wondering whether either base Java (which I doubt, because I checked) or somewhere else reliable (e.g. Apache Commons) provides this, or if I have to write my own. Preferably something lightweight. I don't mind writing it myself, but if there's a "standard" version out there somewhere I'd at least like to look at it first.
Take a look at guavas RateLimiter:
A rate limiter. Conceptually, a rate limiter distributes permits at a
configurable rate. Each acquire() blocks if necessary until a permit
is available, and then takes it. Once acquired, permits need not be
released. Rate limiters are often used to restrict the rate at which
some physical or logical resource is accessed. This is in contrast to
Semaphore which restricts the number of concurrent accesses instead of
the rate (note though that concurrency and rate are closely related,
e.g. see Little's Law).
Its threadsafe, but still #Beta. Might be worth a try anyway.
You would have to wrap each call to the Executor with respect to the rate limiter. For a more clean solution you could create some kind of wrapper for the ExecutorService.
From the javadoc:
final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
void submitTasks(List<Runnable> tasks, Executor executor) {
for (Runnable task : tasks) {
rateLimiter.acquire(); // may wait
executor.execute(task);
}
}
The Java Executor doesn't offer such a limitation, only limitation by amount of threads, which is not what you are looking for.
In general the Executor is the wrong place to limit such actions anyway, it should be at the moment where the Thread tries to call the outside server. You can do this for example by having a limiting Semaphore that threads wait on before they submit their requests.
Calling Thread:
public void run() {
// ...
requestLimiter.acquire();
connection.send();
// ...
}
While at the same time you schedule a (single) secondary thread to periodically (like every 60 seconds) releases acquired resources:
public void run() {
// ...
requestLimiter.drainPermits(); // make sure not more than max are released by draining the Semaphore empty
requestLimiter.release(MAX_NUM_REQUESTS);
// ...
}
no more than say 100 tasks can be processed in a second -- if more
tasks get submitted they should get queued and executed later
You need to look into Executors.newFixedThreadPool(int limit). This will allow you to limit the number of threads that can be executed simultaneously. If you submit more than one thread, they will be queued and executed later.
ExecutorService threadPool = Executors.newFixedThreadPool(100);
Future<?> result1 = threadPool.submit(runnable1);
Future<?> result2 = threadPool.submit(runnable2);
Futurte<SomeClass> result3 = threadPool.submit(callable1);
...
Snippet above shows how you would work with an ExecutorService that allows no more than 100 threads to be executed simultaneously.
Update:
After going over the comments, here is what I have come up with (kinda stupid). How about manually keeping a track of threads that are to be executed ? How about storing them first in an ArrayList and then submitting them to the Executor based on how many threads have already been executed in the last one second.
So, lets say 200 tasks have been submitted into our maintained ArrayList, We can iterate and add 100 to the Executor. When a second passes, we can add few more threads based on how many have completed in theExecutor and so on
Depending on the scenario, and as suggested in one of the previous responses, the basic functionalities of a ThreadPoolExecutor may do the trick.
But if the threadpool is shared by multiple clients and you want to throttle, to restrict the usage of each one of them, making sure that one client won't use all the threads, then a BoundedExecutor will do the work.
More details can be found in the following example:
http://jcip.net/listings/BoundedExecutor.java
Personally I found this scenario quite interesting. In my case, I wanted to stress that the interesting phase to throttle is the consuming side one, as in classical Producer/Consumer concurrent theory. That's the opposite of some of the suggested answers before. This is, we don't want to block the submitting thread, but block the consuming threads based in a rate (tasks/second) policy. So, even if there are tasks ready in the queue, executing/consuming Threads may block waiting to meet the throtle policy.
That said, I think a good candidate would be the Executors.newScheduledThreadPool(int corePoolSize). This way you would need a simple queue in front of the executor (a simple LinkedBlockingQueue would suit), and then schedule a periodic task to pick actual tasks from the queue (ScheduledExecutorService.scheduleAtFixedRate). So, is not an straightforward solution, but it should perform goog enough if you try to throttle the consumers as discussed before.
Can limit it inside Runnable:
public static Runnable throttle (Runnable realRunner, long delay) {
Runnable throttleRunner = new Runnable() {
// whether is waiting to run
private boolean _isWaiting = false;
// target time to run realRunner
private long _timeToRun;
// specified delay time to wait
private long _delay = delay;
// Runnable that has the real task to run
private Runnable _realRunner = realRunner;
#Override
public void run() {
// current time
long now;
synchronized (this) {
// another thread is waiting, skip
if (_isWaiting) return;
now = System.currentTimeMillis();
// update time to run
// do not update it each time since
// you do not want to postpone it unlimited
_timeToRun = now+_delay;
// set waiting status
_isWaiting = true;
}
try {
Thread.sleep(_timeToRun-now);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// clear waiting status before run
_isWaiting = false;
// do the real task
_realRunner.run();
}
}};
return throttleRunner;
}
Take from JAVA Thread Debounce and Throttle

500 Worker Threads, what kind of thread pool?

I am wondering if this is the best way to do this. I have about 500 threads that run indefinitely, but Thread.sleep for a minute when done one cycle of processing.
ExecutorService es = Executors.newFixedThreadPool(list.size()+1);
for (int i = 0; i < list.size(); i++) {
es.execute(coreAppVector.elementAt(i)); //coreAppVector is a vector of extends thread objects
}
The code that is executing is really simple and basically just this
class aThread extends Thread {
public void run(){
while(true){
Thread.sleep(ONE_MINUTE);
//Lots of computation every minute
}
}
}
I do need a separate threads for each running task, so changing the architecture isn't an option. I tried making my threadPool size equal to Runtime.getRuntime().availableProcessors() which attempted to run all 500 threads, but only let 8 (4xhyperthreading) of them execute. The other threads wouldn't surrender and let other threads have their turn. I tried putting in a wait() and notify(), but still no luck. If anyone has a simple example or some tips, I would be grateful!
Well, the design is arguably flawed. The threads implement Genetic-Programming or GP, a type of learning algorithm. Each thread analyzes advanced trends makes predictions. If the thread ever completes, the learning is lost. That said, I was hoping that sleep() would allow me to share some of the resources while one thread isn't "learning"
So the actual requirements are
how can I schedule tasks that maintain
state and run every 2 minutes, but
control how many execute at one time.
If your threads are not terminating, this is the fault of the code within the thread, not the thread pool. For more detailed help you will need to post the code that is being executed.
Also, why do you put each Thread to sleep when it is done; wouldn't it be better just to let it complete?
Additionally, I think you are misusing the thread pool by having a number of threads equal to the number of tasks you wish to execute. The point of a thread pool is to put a constraint on the number of resources used; this approach is no better than not using a thread pool at all.
Finally, you don't need to pass instances of Thread to your ExecutorService, just instances of Runnable. ExecutorService maintains its own pool of threads which loop indefinitely, pulling work off of an internal queue (the work being the Runnables you submit).
Why not used a ScheduledExecutorService to schedule each task to run once per minute, instead of leaving all these threads idle for a full minute?
ScheduledExecutorService workers =
Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
for (Runnable task : list) {
workers.scheduleWithFixedDelay(task, 0, 1, TimeUnit.MINUTES);
}
What do you mean by, "changing the architecture isn't an option"? If you mean that you can't modify your task at all (specifically, the tasks have to loop, instead of running once, and the call to Thread.sleep() can't be removed), then "good performance isn't an option," either.
I'm not sure your code is semantically correct in how it's using a thread pool. ExecutionService creates and manages threads internally, a client should just supply an instance of Runnable, whose run() method will be executed in context of one of pooled threads. You can check my example. Also note that each running thread takes ~10Mb of system memory for the stack, and on linux the mapping of java-to-native threads is 1-to-1.
Instead of putting a tread to sleep you should let it return and use a ThreadPoolexecutor to execute work posted every minute to your work queue.
To answer your question, what type of thread pool?
I posted my comments but this really should address your issue. You have a computation that can take 2 seconds to complete. You have many tasks (500) that you want to be completed as fast as possible. The fastest possible throughput you can achieve, assuming there is no IO and or network traffic, is with Runtime.getRuntime().availableProcessors() number of threads.
If you increase your number to 500 threads, then each task will be executing on its own thread, but the OS will schedule a thread out every so often to give to another thread. Thats 125 context switches at any given point. Each context switch will increase the amount of time for each task to run.
The big picture here is that adding more threads does NOT equal greater throughput when you are way over the number of processors.
Edit: A quick update. You dont need to sleep here. When you execute the 500 tasks with 8 processors, each task will complete in the 2 seconds, finish and the thread it was running on will then take the next task and complete that one.
8 Threads is the max that your system can handle, any more and you are slowing yourself down with context switching.
Look at this article http://www.informit.com/articles/article.aspx?p=1339471&seqNum=4 It will give you an overview of how to do it.
This should do what you desire, but not what you asked for :-) You have to take out the Thread.sleep()
ScheduledRunnable.java
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledRunnable
{
public static void main(final String[] args)
{
final int numTasks = 10;
final ScheduledExecutorService ses = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
for (int i = 0; i < numTasks; i++)
{
ses.scheduleAtFixedRate(new MyRunnable(i), 0, 10, TimeUnit.SECONDS);
}
}
private static class MyRunnable implements Runnable
{
private int id;
private int numRuns;
private MyRunnable(final int id)
{
this.id = id;
this.numRuns = 0;
}
#Override
public void run()
{
this.numRuns += 1;
System.out.format("%d - %d\n", this.id, this.numRuns);
}
}
}
This schedules the Runnables every 10 SECONDS to show the behavior.
If you really need to wait a fixed amount of time AFTER processing is complete you might need to play around with which .scheduleXXX method that you need. I think fixedWait will just run it every N amount of time regardless of what the execution time is.
I do need a separate threads for each running task, so changing the architecture isn't an option.
If that is true (for example, making a call to an external blocking function), then create separate threads for them and start them. You can't create a thread pool with a limited number of threads, as a blocking function in one of threads will prevent any other runnable being put into it, and don't gain much creating a thread pool with one thread per task.
I tried making my threadPool size equal to Runtime.getRuntime().availableProcessors() which attempted to run all 500 threads, but only let 8 (4xhyperthreading) of them execute.
When you pass the Thread objects you are creating to thread pool, it only sees that they implement Runnable. Therefore it will run each Runnable to completion. Any loop which stops the run() method returning will not allow the next enqueued task to run; eg:
public static void main (String...args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 0; i < 10; ++i) {
final int task = i;
executor.execute(new Runnable () {
private long lastRunTime = 0;
#Override
public void run () {
for (int iteration = 0; iteration < 4; )
{
if (System.currentTimeMillis() - this.lastRunTime > TIME_OUT)
{
// do your work here
++iteration;
System.out.printf("Task {%d} iteration {%d} thread {%s}.\n", task, iteration, Thread.currentThread());
this.lastRunTime = System.currentTimeMillis();
}
else
{
Thread.yield(); // otherwise, let other threads run
}
}
}
});
}
executor.shutdown();
}
prints out:
Task {0} iteration {1} thread {Thread[pool-1-thread-1,5,main]}.
Task {1} iteration {1} thread {Thread[pool-1-thread-2,5,main]}.
Task {0} iteration {2} thread {Thread[pool-1-thread-1,5,main]}.
Task {1} iteration {2} thread {Thread[pool-1-thread-2,5,main]}.
Task {0} iteration {3} thread {Thread[pool-1-thread-1,5,main]}.
Task {1} iteration {3} thread {Thread[pool-1-thread-2,5,main]}.
Task {0} iteration {4} thread {Thread[pool-1-thread-1,5,main]}.
Task {2} iteration {1} thread {Thread[pool-1-thread-1,5,main]}.
Task {1} iteration {4} thread {Thread[pool-1-thread-2,5,main]}.
Task {3} iteration {1} thread {Thread[pool-1-thread-2,5,main]}.
Task {2} iteration {2} thread {Thread[pool-1-thread-1,5,main]}.
Task {3} iteration {2} thread {Thread[pool-1-thread-2,5,main]}.
Task {2} iteration {3} thread {Thread[pool-1-thread-1,5,main]}.
Task {3} iteration {3} thread {Thread[pool-1-thread-2,5,main]}.
Task {2} iteration {4} thread {Thread[pool-1-thread-1,5,main]}.
...
showing that the first (thread pool size) tasks run to completion before the next tasks get scheduled.
What you need to do is create tasks which run for a while, then let other tasks run. Quite how you structure these depends on what you want to achieve
whether you want all the tasks to run at the same time, the all wait for a minute, then all run at the same time again, or whether the tasks are not synchronised with each other
whether you really wanted each task to run at a one-minute interval
whether your tasks are potentially blocking or not, and so really require separate threads
what behaviour is expected if a task blocks longer than the expected window for running
what behaviour is expected if a task blocks longer than the repeat rate (blocks for more than one minute)
Depending on the answers to these, some combination of ScheduledExecutorService, semaphores or mutexes can be used to co-ordinate the tasks. The simplest case is the non-blocking, non-synchronous tasks, in which case use a ScheduledExecutorService directly to run your runnables once every minute.
Can you rewrite your project for using some agent-based concurrency framework, like Akka?
You can certainly find some improvement in throughput by reducing the number of threads to what the system can realistically handle. Are you open to changing the design of the thread a bit? It'll unburden the scheduler to put the sleeping ones in a queue instead of actually having hundreds of sleeping threads.
class RepeatingWorker implements Runnable {
private ExecutorService executor;
private Date lastRan;
//constructor takes your executor
#Override
public void run() {
try {
if (now > lastRan + ONE_MINUTE) {
//do job
lastRan = now;
} else {
return;
} finally {
executor.submit(this);
}
}
}
This preserves your core semantic of 'job repeats indefinitely, but waits at least one minute between executions' but now you can tune the thread pool to something the machine can handle and the ones that aren't working are in a queue instead of loitering about in the scheduler as sleeping threads. There is some wait busy behavior if nobody's actually doing anything, but I am assuming from your post that the entire purpose of the application is to run these threads and it's currently railing your processors. You may need to tune around that if room has to be made for other things :)
You need a semaphore.
class AThread extends Thread {
Semaphore sem;
AThread(Semaphore sem) {
this.sem = sem;
}
public void run(){
while(true){
Thread.sleep(ONE_MINUTE);
sem.acquire();
try {
//Lots of computation every minute
} finally {
sem.release();
}
}
}
}
When instantiating the AThreads you need to pass the same semaphore instance:
Semaphore sem = new Semaphore(MAX_AVAILABLE, true);
Edit: Who voted down can please explain why? There is something wrong in my solution?

Categories

Resources