I have a Callable task which I wish to submit to an Executor:
public static final class PersonalTask implements Callable<Object> {
private final String name;
private final int sleep;
public PersonalTask(String name, int sleep) {
this.name = name;
this.sleep = sleep;
}
#Override
public Object call() throws Exception {
System.out.format("My name is %s and I'm sleeping for %d seconds%n", name, sleep);
Thread.sleep(sleep * 1000);
return null;
}
}
Each task contains the name of the person who has requested the task to be executed, and some period of sleeping. This sleep duration is a proxy for the real use-case, which invokes some expensive operation.
To facilitate these tasks, I'm using a fixed thread pool with 5 threads:
private static final ExecutorService executor = Executors.newFixedThreadPool(5);
To illustrate my problem, I would like to submit the following to the thread pool:
public static void main(String[] args) throws Exception {
List<PersonalTask> tasks = Arrays.asList(new PersonalTask[] {
new PersonalTask("Bob", 10), new PersonalTask("Bob", 10),
new PersonalTask("Bob", 10), new PersonalTask("Bob", 10),
new PersonalTask("Bob", 10), new PersonalTask("Bob", 10),
new PersonalTask("Eric", 1), new PersonalTask("Janice", 2) });
executor.invokeAll(tasks);
}
The output from this is:
My name is Bob and I'm sleeping for 10 seconds
My name is Bob and I'm sleeping for 10 seconds
My name is Bob and I'm sleeping for 10 seconds
My name is Bob and I'm sleeping for 10 seconds
My name is Bob and I'm sleeping for 10 seconds
*** PAUSE FOR 10 SECONDS ***
My name is Bob and I'm sleeping for 10 seconds
My name is Eric and I'm sleeping for 1 seconds
My name is Janice and I'm sleeping for 2 seconds
This is because the Bob tasks to sleep for 10 seconds saturate the 5 threads available, and the remaining tasks -- specifically those belonging to Eric and Janice -- have to wait for those to finish.
This is unfair! The large number / slow jobs Bob has submitted are saturating the available threads and are starving Eric and Jane.
I would like to provide the ExecutorService with a mechanism to discriminate on the tasks it is asked to schedule, so I may come up with a fairer solution.
I would like to keep this very simple for now. All of Bob's tasks should be processed by the same thread in the pool. To keep this simple, I'd like to take PersonalTask.name.hashCode() % threadPoolSize and use that to pick which thread to use.
This would mean that Bob can only ever use one of the available 5 threads. This would leave the 4 remaining threads free to process other people's requests.
I realize this is not perfect, as other people with the same hash % size value would still be held up behind Bob. In fact, they'd now have to wait much, much longer as there are 6 * 10 second jobs ahead of them in that thread's queue.
What patterns can I use in Java to accomplish this?
Use your own implementation of BlockingQueue (like a PriorityBlockingQueue) and a manually constructed ThreadPoolExecutor that accepts as parameter your BlockingQueue. In your BlockingQueue implementation you could keep a Set of all your existing persons (in tasks) and iterate through it and return the next available Task of the person.
In your executor service, use a Map<Object,Queue> to map each User to their tasks, and relate this user to their Thread in the thread pool, maybe in another map Map<Object,Thread>.
Related
I have threads which are given random number (1 to n) and are instructed to print them in sorted order. I used semaphore such that I acquire the number of permits = random number and release one permit more than what was acquired.
acquired = random number; released = 1+random number
Initial permit count for semaphore is 1. So thread with random number 1 should get permit and then 2 and so on.
This is supported as per the documentation given below
There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire().
The problem is my program gets stuck after 1 for n>2.
My program is given below:
import java.util.concurrent.Semaphore;
public class MultiThreading {
public static void main(String[] args) {
Semaphore sem = new Semaphore(1,false);
for(int i=5;i>=1;i--)
new MyThread(i, sem);
}
}
class MyThread implements Runnable {
int var;Semaphore sem;
public MyThread(int a, Semaphore s) {
var =a;sem=s;
new Thread(this).start();
}
#Override
public void run() {
System.out.println("Acquiring lock -- "+var);
try {
sem.acquire(var);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(var);
System.out.println("Releasing lock -- "+var);
sem.release(var+1);
}
}
Output is :
Acquiring lock -- 4
Acquiring lock -- 5
Acquiring lock -- 3
Acquiring lock -- 2
Acquiring lock -- 1
1
Releasing lock -- 1
While If I modify my code with tryAcquire, it runs perfectly well.
Below is new run implementation
#Override
public void run() {
boolean acquired = false;
while(!acquired) {
acquired = sem.tryAcquire(var);
}
System.out.println(var);
sem.release(var+1);
}
Can someone please explain the semaphore's permit acquire mechanism when mulitple threads are waiting with different permit request??
It's a clever strategy, but you're misunderstanding how Sempahore hands out permits. If you run your code enough times you'll actually see it reach step two:
Acquiring lock -- 5
Acquiring lock -- 1
1
Releasing lock -- 1
Acquiring lock -- 3
Acquiring lock -- 2
2
Acquiring lock -- 4
Releasing lock -- 2
If you keep on re-running it enough times you'd actually see it successfully finish. This happens because of how Semaphore hands out permits. You're assuming Semaphore will try to accommodate an acquire() call as soon as it has enough permits to do so. If we look carefully at the documentation for Semaphore.aquire(int) we'll see that is not the case (emphasis mine):
If insufficient permits are available then the current thread becomes disabled for thread scheduling purposes and lies dormant until ... some other thread invokes one of the release methods for this semaphore, the current thread is next to be assigned permits and the number of available permits satisfies this request.
In other words Semaphore keeps a queue of pending acquire request and, upon each call to .release(), only checks the head of the queue. In particular if you enable fair queuing (set the second constructor argument to true) you'll see even step one doesn't occur, because step 5 is (usually) the first in the queue and even new acquire() calls that could be fulfilled will be queued up behind the other pending calls.
In short this means you cannot rely on .acquire() to return as soon as possible, as your code assumes.
By using .tryAcquire() in a loop instead you avoid making any blocking calls (and therefore put a lot more load on your Semaphore) and as soon as the necessary number of permits becomes available a tryAcquire() call will successfully obtain them. This works but is wasteful.
Picture a wait-list at a restaurant. Using .aquire() is like putting your name on the list and waiting to be called. It may not be perfectly efficient, but they'll get to you in a (reasonably) fair amount of time. Imagine instead if everyone just shouted at the host "Do you have a table for n yet?" as often as they could - that's your tryAquire() loop. It may still work out (as it does in your example) but it's certainly not the right way to go about it.
So what should you do instead? There's a number of possibly useful tools in java.util.concurrent, and which is best somewhat depends on what exactly you're trying to do. Seeing as you're effectively having each thread start the next one I might use a BlockingQueue as the synchronization aid, pushing the next step into the queue each time. Each thread would then poll the queue, and if it's not the activated thread's turn replace the value and wait again.
Here's an example:
public class MultiThreading {
public static void main(String[] args) throws Exception{
// Use fair queuing to prevent an out-of-order task
// from jumping to the head of the line again
// try setting this to false - you'll see far more re-queuing calls
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(1, true);
for (int i = 5; i >= 1; i--) {
Thread.sleep(100); // not necessary, just helps demonstrate the queuing behavior
new MyThread(i, queue).start();
}
queue.add(1); // work starts now
}
static class MyThread extends Thread {
int var;
BlockingQueue<Integer> queue;
public MyThread(int var, BlockingQueue<Integer> queue) {
this.var = var;
this.queue = queue;
}
#Override
public void run() {
System.out.println("Task " + var + " is now pending...");
try {
while (true) {
int task = queue.take();
if (task != var) {
System.out.println(
"Task " + var + " got task " + task + " instead - re-queuing");
queue.add(task);
} else {
break;
}
}
} catch (InterruptedException e) {
// If a thread is interrupted, re-mark the thread interrupted and terminate
Thread.currentThread().interrupt();
return;
}
System.out.println("Finished task " + var);
System.out.println("Registering task " + (var + 1) + " to run next");
queue.add(var + 1);
}
}
}
This prints the following and terminates successfully:
Task 5 is now pending...
Task 4 is now pending...
Task 3 is now pending...
Task 2 is now pending...
Task 1 is now pending...
Task 5 got task 1 instead - re-queuing
Task 4 got task 1 instead - re-queuing
Task 3 got task 1 instead - re-queuing
Task 2 got task 1 instead - re-queuing
Finished task 1
Registering task 2 to run next
Task 5 got task 2 instead - re-queuing
Task 4 got task 2 instead - re-queuing
Task 3 got task 2 instead - re-queuing
Finished task 2
Registering task 3 to run next
Task 5 got task 3 instead - re-queuing
Task 4 got task 3 instead - re-queuing
Finished task 3
Registering task 4 to run next
Task 5 got task 4 instead - re-queuing
Finished task 4
Registering task 5 to run next
Finished task 5
Registering task 6 to run next
The Javadoc for Semaphore.acquire(int) says:
If insufficient permits are available then the current thread becomes
disabled for thread scheduling purposes and lies dormant until one of
two things happens:
Some other thread invokes one of the release methods for this semaphore,
the current thread is next to be assigned permits and the number of
available permits satisfies this request [or the thread is interrupted].
The thread that is "next to be assigned" is probably thread 4 in your example. It is waiting until there are 4 permits available. However, thread 1, which gets a permit upon calling acquire(), only releases 2 permits, which is not enough to unblock thread 4. Meanwhile, thread 2, which is the only thread for which there are sufficient permits, is not the next to be assigned, so it doesn't get the permits.
Your modified code runs fine because the threads don't block when they try to get a semaphore; they just try again, going to the back of the line. Eventually thread 2 reaches the front of the line and is thus next to be assigned, and so gets its permits.
I want to create a cached thread pool, but it acts as a fixed one. Currently I have this code:
public class BackgroundProcesses {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//ExecutorService threadPool2 = Executors.newCachedThreadPool();
ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
for (int i = 0; i < 800; i++) {
Callable<String> task = new Task();
threadPool.submit(task);
}
}
}
class Task implements Callable<String> {
#Override
public String call() throws Exception {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " is ready");
return "";
}
}
If I run the code I get output:
pool-1-thread-1 is ready
pool-1-thread-2 is ready
pool-1-thread-1 is ready
pool-1-thread-2 is ready
...
Meaning only 2 threads are doing all the work and no new worker threads are added to the pool. Shouldn't the threadpool spawn more threads if tasks are waiting in queue (up to 10 in my case)?
I don't want to use Executors.newCachedThreadPool() because it has practically no upper limit on maximum threads and it has corePoolSize 0. I want to have some threads ready at all times for better responsiveness.
----- edit 1 -----
Thank you Aleksey for the answer. Setting capacity to queue is making it behave as expected, but now I have a new problem.
The amount of background tasks vary a lot. Most of the time 0 but can go up to 50 concurrent tasks for short periods. What would be an efficient way to handle this? Keep in mind most background tasks would be short-lived (< 1s) but a few long lived tasks (> 1min) as well.
If I set my threadpool up like this:
ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
I will most likely get RejectedExecutionException with peak usage. However if I set threadpool up like this:
ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200));
Then no new worker threads will ever be added because the queue won't max out.
The CPU has at least 4 cores so this would be wasteful in my opinion. And most of the time there isn't any background tasks at all (80% of up time), so keeping a fixed thread pool would also be wasteful in my opinion.
ThreadPoolExecutor Javadoc says:
When a new task is submitted in method execute(Runnable), and fewer
than corePoolSize threads are running, a new thread is created to
handle the request, even if other worker threads are idle. If there
are more than corePoolSize but less than maximumPoolSize threads
running, a new thread will be created only if the queue is full
Your LinkedBlockingQueue is never full, because it does not have an upper bound on the number of elements. Changing new LinkedBlockingQueue() to new LinkedBlockingQueue(10) would solve that.
I have 10 threads filling unique codes in 10 tables simultaneously. Each thread filling up million records. After sometimes 7 tables got filled up but the rest 3 are still filling up. I want to indulge the free 7 threads in filling up the tables simultaneously with the running 3 threads can this be done??
String noOfCodes = ""+((Integer.parseInt(totalOfCodes))/10);
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
String threadNo = ""+i;
Runnable worker = new CodeGeneratorDAO(pgmId, digits, points, validity, noOfCodes, product, threadNo);
executor.execute(worker);
resp.setSuccess(true);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
A simple solution is to define a Runnable executing a smaller task that your current Runnable. Breaking down the tasks will smooth the overall execution time.
You say that your Runnable "fills up 1000 records", so define your Runnable as filling up 1 record and submit all your 10 * 1000 records to be updated to your ExecutorService:
ExecutorService executor = Executors.newFixedThreadPool(10);
for(Runnable oneRecordRunnable : allRunnables) {
executor.submit(oneRecordRunnable);
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
As a side note, I replaced your cpu-burning while(true) loop by the awaitTermination method.
I'm trying to do create several scheduled tasks in java.
However, when I add several tasks, some of them crash returning this exception:
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask#219baf0b rejected from java.util.concurrent.ScheduledThreadPoolExecutor#74010c69[Shutting down, pool size = 2, active threads = 0, queued tasks = 4, completed tasks = 0]
This is the code I am using:
final ScheduledExecutorService schExService;
/**
* Constructor per defecte de TaskSchedulker. AquĆ s'inicaran els atributs i
* s'instanciaran els objectes necessaris per disposar d'un programador com
* el descrit totalement funcional.
*/
public TaskScheduler() {
schExService = Executors.newScheduledThreadPool( 2 );
}
public void addTask(){
final Runnable ob = new ExecutaFil(tskParams);
schExService.schedule(ob, toSeconds( timeToWait ), TimeUnit.SECONDS);
}
And I'm triggering addTask method several times.
ExecutaFil is is just a class implementing Runnable with a sleep in it.
Any tip?
I tried changing the pool value (from 2 to for example, 100) and it's ignoring. Pool size is never higher than 4. I guess it's directly related to processor? How can I fix this?
rejected from java.util.concurrent.ScheduledThreadPoolExecutor#74010c69[Shutting down, pool size = 2, active threads = 0, queued tasks = 4, completed tasks = 0]
This means you shutdown the executor by calling shutdown() on it. If you want to keep adding tasks, don't shut it down.
I guess it's directly related to processor?
Nothing in the error message suggests this.
I want to simulate a scheduler in java. I have three threads defined. Now I want to execute Thread 1 to be take 10% time, Thread 2 to take 30% and Thread 3 to take remaining 60% of time approximately.
All the three threads are continous monitoring tasks which will never end.
i.e. If I execute the program for 100 minutes, then Thread 1 executes for 10 mins, Thread 2 for 30 mins & Thread 3 for 60 minutes.
and also whenever threads are being shifted (i.e. another threading going into running state), I should print that "Thread x executed for Y seconds"
Can any one please provide some pointers on achieving the above simulation in java.
This link should be interresting.
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MainThread
{
public static void main(String[] args)
{
int corePoolSize = 2;
ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(corePoolSize);
/*
* This will execute the WorkerThread immediately
*/
stpe.execute(new WorkerThread("WorkerThread-Running-Immediately"));
/*
* This will execute the WorkerThread only once after 10 Seconds
*/
stpe.schedule(new WorkerThread("WorkerThread-Scheduled-After-10-seconds"), 10, TimeUnit.SECONDS);
/*
* This will execute the WorkerThread continuously for every 5 seconds with an initial delay of 10
* seconds for the first WorkerThread to start execution cycle. In this case, whether the first
* WorkerThread is completed or not, the second WorkerThread will start exactly after 5 seconds hence
* called schedule at fixed rate. This continues till 'n' threads are executed.
*/
stpe.scheduleAtFixedRate(new WorkerThread("WorkerThread-Running-At-Fixed-Rate"), 10, 5, TimeUnit.SECONDS);
/*
* This will execute the WorkerThread continuously with an initial delay of 10 seconds for the first
* WorkerThread to start execution cycle. Once the first thread execution completes then a delay of 5
* Seconds is introduced so that the next WorkerThread execution cycle starts. This continues till
* 'n' thread are executed. This is called schedule each thread with a fixed delay.
*/
stpe.scheduleWithFixedDelay(new WorkerThread("WorkerThread-Running-With-Fixed-Delay"), 10, 5, TimeUnit.SECONDS);
}
}
And a worker thread :
public class WorkerThread implements Runnable
{
private String threadName = null;
public WorkerThread(String threadName)
{
this.threadName = threadName;
}
public void run()
{
System.out.println(this.threadName + " started...");
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(this.threadName + " ended...");
}
}