I am reading the source code of ThreadPoolExecutor.java, for the execute method below:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
Assume the thread pool has 2 core threads and set the max pool size is 4.
I can understand the code if (workerCountOf(c) < corePoolSize) { addWorkder(..) }, it means if currently the core threads count is less than core poll size, just create a new thread to handle the runnable command.
What I cannot understand is, say if we had already called execute(runnable) two times, and each of them needs long time to complete, so they are still busy now, and now we are calling the 3rd time.
What the code will do? I think the code goes to if (isRunning(c) && workQueue.offer(command)) { so the command gets added to work queue. However, I don't understand this 3rd command will be executed by which thread. As per the code else if (workerCountOf(recheck) == 0), I think worker count should be 2 because we have already added two workers.
So my question is when will the 3rd worker be added?
--Edit--
My testing code:
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
2,
4,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(4)
);
threadPoolExecutor.execute(new Command("A"));
threadPoolExecutor.execute(new Command("B"));
threadPoolExecutor.execute(new Command("C"));
}
static class Command implements Runnable {
private String task;
Command(String task) {
this.task = task;
}
#Override
public void run() {
try {
Thread.sleep(1000 * 10);
System.out.println(new Date() + " - " + Thread.currentThread().getName() + " : " + task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
It prints:
Thu Jun 13 17:44:30 CST 2019 - pool-1-thread-1 : A
Thu Jun 13 17:44:30 CST 2019 - pool-1-thread-2 : B
Thu Jun 13 17:44:40 CST 2019 - pool-1-thread-1 : C
With the testing code I expect the core workers are keep being busy for 10 seconds so when execute("C") I want to hit the case 'core workers are busy and the 3rd worker will be added', but it seems that there is no the 3rd worker? Sorry but what's wrong?
Thanks.
I want to hit the case 'core workers are busy and the 3rd worker will be added'
Then you also have to fill up the queue.
Javadoc says:
When a new task is submitted in method execute(java.lang.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.
Suppose
N = no of thread in currently in the pool.
C = core size of pool
M = maximum size of pool.
BQ = Bounded Blocking Queue.(having a predefined capacity).
UQ = Unbounded Blocking Queue.(without a predefined capacity).
DHQ = Direct hand-offs Queue.
Then
1. If BQ
A. If N <= C , then thread always created when task is submitted, idle
thread is present in pool or not doesn't matter.
B. Once the core pool size is reached, executor start puting
the new task in queue if there is no idle thread.
If there is any idle thread then the task is assigned to idle thread.
C. When BQ is full, then executor start creating again new thread till
its value reached to M if there is no idle thread.
So the new thread creation after reaching N=C value is start when queue
is full.
D. Once N=M reached and BQ is also full , then executor not accept any
task.It throw exception.
2. If UQ
A. Same as above
B. Same as above
C. Not applicable. Why ? because it is unbounded queue.
(UQ capacity is Integer.MAX_VALUE)
D. No effect of M. Why ?
Since creation of new thread again is start after the queue is full,but
in the case UQ queue is never full.
So new thread never created once reach N=C for the new task submitted.
Means thread in thread pool always be equal to C (N=C always) in case
UQ , whatever the value of M
3. If DHQ
A. The direct hand-offs queue never put the task in queue, its immediately
assigned task to thread if any thread is idle ,if not then it create new
one.(task in queue is always 0)
B. The concept of C is not applicable in this queue.Thread created till
its value reach M.
C. Once the N value reach M (N=M), and try to submit the task ,it reject
the task.
Related
I am running into an issue where if I attempt to resize a ThreadPoolExecutor's core pool size to a different number after the pool has been created, then intermittently, some tasks are rejected with a RejectedExecutionException even though I never submit more than queueSize + maxPoolSize number of tasks.
The problem that I am trying to solve is to extend ThreadPoolExecutor that resizes its core threads based on the pending executions sitting in the thread pool's queue. I need this because by default a ThreadPoolExecutor will create a new Thread only if the queue is full.
Here is a small self-contained Pure Java 8 program that demonstrates the problem.
import static java.lang.Math.max;
import static java.lang.Math.min;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolResizeTest {
public static void main(String[] args) throws Exception {
// increase the number of iterations if unable to reproduce
// for me 100 iterations have been enough
int numberOfExecutions = 100;
for (int i = 1; i <= numberOfExecutions; i++) {
executeOnce();
}
}
private static void executeOnce() throws Exception {
int minThreads = 1;
int maxThreads = 5;
int queueCapacity = 10;
ThreadPoolExecutor pool = new ThreadPoolExecutor(
minThreads, maxThreads,
0, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(queueCapacity),
new ThreadPoolExecutor.AbortPolicy()
);
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(() -> resizeThreadPool(pool, minThreads, maxThreads),
0, 10, TimeUnit.MILLISECONDS);
CompletableFuture<Void> taskBlocker = new CompletableFuture<>();
try {
int totalTasksToSubmit = queueCapacity + maxThreads;
for (int i = 1; i <= totalTasksToSubmit; i++) {
// following line sometimes throws a RejectedExecutionException
pool.submit(() -> {
// block the thread and prevent it from completing the task
taskBlocker.join();
});
// Thread.sleep(10); //enabling even a small sleep makes the problem go away
}
} finally {
taskBlocker.complete(null);
scheduler.shutdown();
pool.shutdown();
}
}
/**
* Resize the thread pool if the number of pending tasks are non-zero.
*/
private static void resizeThreadPool(ThreadPoolExecutor pool, int minThreads, int maxThreads) {
int pendingExecutions = pool.getQueue().size();
int approximateRunningExecutions = pool.getActiveCount();
/*
* New core thread count should be the sum of pending and currently executing tasks
* with an upper bound of maxThreads and a lower bound of minThreads.
*/
int newThreadCount = min(maxThreads, max(minThreads, pendingExecutions + approximateRunningExecutions));
pool.setCorePoolSize(newThreadCount);
pool.prestartAllCoreThreads();
}
}
Why should the pool ever throw a RejectedExecutionException if I never submit more that the queueCapacity+maxThreads. I am never changing the max threads so by ThreadPoolExecutor's definition, it should either accommodate the task in a Thread or to the queue.
Of course, if I never resize the pool, then the thread pool never rejects any submissions. This is also hard to debug since adding any sort of delays in the submissions makes the problem go away.
Any pointers on how to fix the RejectedExecutionException?
Here is a scenario why this is happening:
In my example I use minThreads = 0, maxThreads = 2 and queueCapacity = 2 to make it shorter.
The first command gets submitted, this is done in the method execute:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
for this command workQueue.offer(command) than addWorker(null, false) is executed.
The worker thread first takes this command out of the queue in the thread run method, so at this time the queue still has one command,
The second command gets submitted this time workQueue.offer(command) is executed. Now the queue is full
Now the ScheduledExecutorService executes the resizeThreadPool method which calls setCorePoolSize with maxThreads.
Here is the method setCorePoolSize:
public void setCorePoolSize(int corePoolSize) {
if (corePoolSize < 0)
throw new IllegalArgumentException();
int delta = corePoolSize - this.corePoolSize;
this.corePoolSize = corePoolSize;
if (workerCountOf(ctl.get()) > corePoolSize)
interruptIdleWorkers();
else if (delta > 0) {
// We don't really know how many new threads are "needed".
// As a heuristic, prestart enough new workers (up to new
// core size) to handle the current number of tasks in
// queue, but stop if queue becomes empty while doing so.
int k = Math.min(delta, workQueue.size());
while (k-- > 0 && addWorker(null, true)) {
if (workQueue.isEmpty())
break;
}
}
}
This method adds one worker using addWorker(null, true). No there are 2 worker queues running, the maximum and the queue is full.
The third command gets submitted and fails because workQueue.offer(command) and addWorker(command, false) fails, leading to the Exception:
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask#24c22fe rejected from java.util.concurrent.ThreadPoolExecutor#cd1e646[Running, pool size = 2, active threads = 2, queued tasks = 2, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at ThreadPoolResizeTest.executeOnce(ThreadPoolResizeTest.java:60)
at ThreadPoolResizeTest.runTest(ThreadPoolResizeTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365)
I think to solve this problem you should set the capacityof the queue to the maximum of commands you want to execute.
Not sure if this qualifies as bug. This is the behavior when the additional workers threads are created after the queue is full but this has been kind of noted in java docs that caller has to deal with tasks being rejected.
Java docs
Factory for new threads. All threads are created using this
factory (via method addWorker). All callers must be prepared
for addWorker to fail, which may reflect a system or user's
policy limiting the number of threads. Even though it is not
treated as an error, failure to create threads may result in
new tasks being rejected or existing ones remaining stuck in
the queue.
When you resize the core pool size, lets say increase, the additional workers are created (addWorker method in setCorePoolSize) and the call to create additional work (addWorker method from execute) is rejected when the addWorker returns false (add Worker last code snippet) as the enough additional workers are already created by setCorePoolSize but not run yet to reflect the update in the queue.
Relevant parts
Compare
public void setCorePoolSize(int corePoolSize) {
....
int k = Math.min(delta, workQueue.size());
while (k-- > 0 && addWorker(null, true)) {
if (workQueue.isEmpty())
break;
}
}
public void execute(Runnable command) {
...
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
private boolean addWorker(Runnable firstTask, boolean core) {
....
if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize))
return false;
}
Use custom retry rejection execution handler ( This should work for your case as you have upper bound as max pool size ). Please adjust as needed.
public static class RetryRejectionPolicy implements RejectedExecutionHandler {
public RetryRejectionPolicy () {}
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
while(true)
if(e.getQueue().offer(r)) break;
}
}
}
ThreadPoolExecutor pool = new ThreadPoolExecutor(
minThreads, maxThreads,
0, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(queueCapacity),
new ThreadPoolResizeTest.RetryRejectionPolicy()
);
Also note your use of shutdown is not correct as this will not wait for submitted task to complete execution but use with awaitTermination instead.
I was running some tests with parallel processing and made a program that given a matrix of integers re-calcutes each position's value based on the neighbours.
I needed a copy of the matrix so the values wouldn't be overriden and used a CyclicBarrier to merge the results once the partial problems were solved:
CyclicBarrier cyclic_barrier = new CyclicBarrier(n_tasks + 1, new Runnable() {
public void run() {
ParallelProcess.mergeResult();
}
});
ParallelProcess p = new ParallelProcess(cyclic_barrier, n_rows, r_cols); // init
Each task is assigned a portion of the matrix: I'm splitting it in equals pieces by rows. But it might happen that the divisions are not exact so there would be a small piece corresponding to the lasts row that wouldn't be submitted to the thread pool.
Example: if I have 16 rows and n_tasks = 4 no problem, all 4 will be submitted to the pool. But if I had 18 instead, the first 16 ones will be submitted, but not the last two ones.
So I'm forcing a submit if this case happens. Well, I'm not submitting actually, because I am using a fixed thread pool that I created like this ExecutorService e = Executors.newFixedThreadPool(n_tasks). Since all the slots in the pool are occupied and the threads are blocked by the barrier (mybarrier.await() is called in the run method) I couldn't submit it to the pool, so I just used Thread.start().
Let's go to the point. Since I need to take into consideration for the CyclicBarrier the possibility of that chunk remaining, the number of parties must be incremented by 1.
But if this case didn't happen, I would be one party short to trigger the barrier.
What's my solution?:
if (lower_limit != n_rows) { // the remaining chunk to be processed
Thread t = new Thread(new ParallelProcess(lower_limit, n_rows));
t.start();
t.join();
}
else {
cyclic_barrier.await();
}
I feel like I am cheating when using the cyclic_barrier.await() trick to raise the barrier by force.
Is there any other way I could approach this problem so I didn't have to do what I'm doing?
Though this doesn't answer your question about CyclicBarriers, can I recommend using a Phaser? This does have the ability to include the number of parties, and it also allows you to run the mergeResult when a phase is tripped.
So, before you execute an async calculation, simply register. Then inside that calculation have the thread arrive on the phaser. When all threads have arrived, it will advance the phase and can invoke an overriden method onAdvance.
The submission:
ParallelProcess process = new ParallelProcess(lower_limit, n_rows));
phaser.register();
executor.submit(process);
The processor
public void run(){
//do stuff
phaser.arrive();
}
The phaser
Phaser phaser = new Phaser(){
protected boolean onAdvance(int phase, int registeredParties) {
ParallelProcess.mergeResult();
return true;
}
}
Can anybody explain how thread priority works in java. The confusion here is if java does'nt guarantee the implementation of the Thread according to its priority then why is this setpriority() function used for.
My code is as follows :
public class ThreadSynchronization implements Runnable{
public synchronized void run() {
System.out.println("Starting Implementation of Thread "+Thread.currentThread().getName());
for(int i=0;i<10;i++)
{
System.out.println("Thread "+Thread.currentThread().getName()+" value : "+i);
}
System.out.println("Ending Implementation of Thread "+Thread.currentThread().getName());
}
public static void main(String[] args) {
System.out.println("Program starts...");
ThreadSynchronization th1 = new ThreadSynchronization();
Thread t1 = new Thread(th1);
t1.setPriority(1);
synchronized(t1)
{
t1.start();
}
ThreadSynchronization th2 = new ThreadSynchronization();
Thread t2 = new Thread(th2);
t2.setPriority(9);
synchronized (t2) {
t2.start();
}
System.out.println("Program ends...");
}
}
In the above program even if I change the priority I find no difference in the output.
Also a real time application of how thread priority can be used would be of great help.
Thanks.
Thread priority is just a hint to OS task scheduler and is dependent on the underlying OS. OS will try to allocate more resources to a high priority thread but it does not guarantee it. So if your program is dependent on thread priorities than you are in-turn binding your program to underlying OS, which is bad.
From Java Concurrency in Practice:
Avoid the temptation to use thread priorities, since they increase
platform dependence and can cause liveness problems. Most concurrent
applications can use the default priority for all threads.
Thread priority is only a hint to OS task scheduler. Task scheduler will only try to allocate more resources to a thread with higher priority, however there are no explicit guarantees.
In fact, it is not only relevant to Java or JVM. Most non-real time OS use thread priorities (managed or unmanaged) only in a suggestive manner.
Also very important, Priorties are different to every underlying plattform. Therefore you kind of loose your plattform freedom of java. See this summary as well:
Indeed, some priority levels can map to the same "native" priority level. Here's the list (based on the Hotspot code in OpenJDK 6):
Solaris
1 ⇒ 0
2 ⇒ 32
3 ⇒ 64
4 ⇒ 96
5 – 10 ⇒ 127
Of note is that on Solaris, you can't raise the thread priority above normal, only lower it: the priority value for 5 is the same as any of the higher values.
Linux
1 – 10 ⇒ 4 – -5 (nice values)
Of note is that on Linux, different thread priorities in Java do map to distinct priority values at native level.
Windows
1 – 2 ⇒ THREAD_PRIORITY_LOWEST
3 – 4 ⇒ THREAD_PRIORITY_BELOW_NORMAL
5 – 6 ⇒ THREAD_PRIORITY_NORMAL
7 – 8 ⇒ THREAD_PRIORITY_ABOVE_NORMAL
9 – 10 ⇒ THREAD_PRIORITY_HIGHEST
I've developed a lot of multi threaded java applications, and in my opinion if you have to set thead priorities you have another problem. Like a bad algorythm that consumes to much cpu time etc.... I always suggest to not change the java thread prio, since you can't rely on it anyways. (of course there are some scenarios where it makes sense)
There are several situations where setting a priority for a Thread is useful, you just must not start believing in any guarantees that come form such settings, as always: the order of execution with threads is undefined. If you think that your thread will be done earlier if you give it a higher priority, please read the statement above again until that's out of your head. ;)
You should define the priority based on how important it is for this thread to gain execution time compared to the others. Even though the underlaying system guarantees nothing, it still can provide a benefit for those JVMs that support it.
Example: You have a program that does some heavy calculation based on user input in your JFrame. It is a good practice to set those background threads to a low priority, because it is more important that the JFrame is responsive than working on the calculation (which will take a long time to finish anyways, a few more millis won't hurt). The OS will still assign most CPU time to the low priority threads, unless something more important needs it. But then it is good that this more important stuff gets the priority.
Now it could happen that on some systems the priority setting is ignored and the JFrame is again unresponsive, but then this does nothing worse to your code then not setting the priority to low in the first place.
The size of the tasks is too small and probably will complete right after the start. Also, if you have "enough" CPU cores, each worker thread will be allocated to one core, so the result will be the same.
Try the experiment in a different context, first increase the task size (for example by looping one thousand times to one million, without print) then increase the number of threads to exceed the number of cores you have and third, create your threads first and then start all the threads (you cannot start them at once, you will still need to loop through them).
In my case, I have chosen 10 threads because I ran the code on a processor with two hyper-threaded cores, running four simultaneous threads.
My changes to your example:
public class ThreadPriority implements Runnable {
public synchronized void run() {
System.out.println("Starting Implementation of Thread " + Thread.currentThread().getName());
float s = 0;
for (int i = 0; i < 1000; i++)
for (int k = 0; k < 1000000; k++)
s += k;
System.out.println("Ending Implementation of Thread " + Thread.currentThread().getName() + " " + s);
}
Thread t;
public ThreadPriority(String name, int prio) {
t = new Thread(this);
t.setName(name);
t.setPriority(prio);
}
public void start() {
synchronized (t) {
t.start();
}
}
public static void main(String[] args) {
System.out.println("Program starts...");
ThreadPriority[] th = new ThreadPriority[10];
for (int i = 0; i < th.length; i++) {
th[i] = new ThreadPriority("T" + i, i / 2 + 1);
}
for (ThreadPriority tp : th)
tp.start();
System.out.println("Program ending, wait for all the threads to complete");
}
}
Results are:
Program starts...
Starting Implementation of Thread T0
Starting Implementation of Thread T9
Starting Implementation of Thread T8
Starting Implementation of Thread T5
Program ending, wait for all the threads to complete
Starting Implementation of Thread T4
Starting Implementation of Thread T6
Starting Implementation of Thread T7
Starting Implementation of Thread T2
Starting Implementation of Thread T3
Starting Implementation of Thread T1
Ending Implementation of Thread T6 1.7592186E13
Ending Implementation of Thread T7 1.7592186E13
Ending Implementation of Thread T4 1.7592186E13
Ending Implementation of Thread T8 1.7592186E13
Ending Implementation of Thread T9 1.7592186E13
Ending Implementation of Thread T5 1.7592186E13
Ending Implementation of Thread T2 1.7592186E13
Ending Implementation of Thread T0 1.7592186E13
Ending Implementation of Thread T1 1.7592186E13
Ending Implementation of Thread T3 1.7592186E13
As you can see, the low number threads tend to end later, because the high number threads have higher priority. By turning the scale upside down:
for (int i = 0; i < th.length; i++) {
th[i] = new ThreadPriority("T" + i, 9 - i / 2 );
}
The low number threads complete faster than the high ones. Some threads complete even before other threads are started, because they have higher priority compared to the calling program:
Program starts...
Starting Implementation of Thread T0
Starting Implementation of Thread T1
Starting Implementation of Thread T2
Starting Implementation of Thread T3
Program ending, wait for all the threads to complete
Ending Implementation of Thread T2 1.7592186E13
Ending Implementation of Thread T3 1.7592186E13
Ending Implementation of Thread T0 1.7592186E13
Ending Implementation of Thread T1 1.7592186E13
Starting Implementation of Thread T9
Starting Implementation of Thread T4
Starting Implementation of Thread T8
Starting Implementation of Thread T7
Starting Implementation of Thread T5
Starting Implementation of Thread T6
Ending Implementation of Thread T4 1.7592186E13
Ending Implementation of Thread T5 1.7592186E13
Ending Implementation of Thread T7 1.7592186E13
Ending Implementation of Thread T8 1.7592186E13
Ending Implementation of Thread T9 1.7592186E13
Ending Implementation of Thread T6 1.7592186E13
Hope it helps!
package priority;
public class ThreadPriorityApp {
// Note : Thread priority may not be supported in some OS due to underlying task scheduler at OS level
/**
* MyThread is an inner class implementing Thread functionality
*
*/
class MyThread extends Thread {
public MyThread(String threadName) {
super(threadName);
}
public void run() {
System.out.println("Running thread - " + Thread.currentThread().getName());
}
}
public static void main(String[] args) {
//If priority is not set then main priority is set to threads created inside main thread - Parent to child
// Main thread priority - 5, is set to Thread 1 and Thread 2, if not manually assigned (commenting Line #34 and #35)
System.out.println("Main thread priority - " + Thread.currentThread().getPriority());
ThreadPriorityApp threadPriorityApp = new ThreadPriorityApp();
//We are creating two threads
MyThread th = threadPriorityApp.new MyThread("Thread 1");
MyThread th2 = threadPriorityApp.new MyThread("Thread 2");
// Range 1 to 10 - 10 being given as MAX Priority
th.setPriority(Thread.MIN_PRIORITY);
th2.setPriority(Thread.MAX_PRIORITY);
//We have started Thread 1 first and then Thread 2 later
th.start();
th2.start();
// Possible Outcomes(1) (With Priority - Line #34 and #35) :
// Running thread - Thread 2
// Running thread - Thread 1
// Possible Outputs(2) : (Without Priority - commenting Line #34 and #35)
// (1) Running thread - Thread 1
// Running thread - Thread 2
// OR
// (2) Running thread - Thread 2
// Running thread - Thread 1
}
//Happy coding -- Parthasarathy S
}
//The iterative and recursive with memorize both shows count as 1424 for digits of length ten starting with 1.
int[][] b = {{4,6},{6,8},{7,9},{4,8},{0,3,9},{},{1,7,0},{2,6},{1,3},{2,4}};
public int countIterative(int digit, int length) {
int[][] matrix = new int[length][10];
for(int dig =0; dig <=9; dig++){
matrix[0][dig] = 1;
}
for(int len = 1; len < length; len++){
for(int dig =0; dig <=9; dig++){
int sum = 0;
for(int i : b[dig]){
sum += matrix[len-1][i];
}
matrix[len][dig] = sum;
}
}
return matrix[length-1][digit];
}
public int count(int index, int length, int[][] matrix ){
int sum = 0;
if(matrix[length-1][index] > 0){
return matrix[length-1][index];
}
if( length == 1){
return 1;
}
for(int i: b[index] ) {
sum += count(i, length-1,matrix);
}
matrix[length-1][index] = sum;
return sum;
}
I am trying out the executor service in Java, and wrote the following code to run Fibonacci (yes, the massively recursive version, just to stress out the executor service).
Surprisingly, it will run faster if I set the nThreads to 1. It might be related to the fact that the size of each "task" submitted to the executor service is really small. But still it must be the same number also if I set nThreads to 1.
To see if the access to the shared Atomic variables can cause this issue, I commented out the three lines with the comment "see text", and looked at the system monitor to see how long the execution takes. But the results are the same.
Any idea why this is happening?
BTW, I wanted to compare it with the similar implementation with Fork/Join. It turns out to be way slower than the F/J implementation.
public class MainSimpler {
static int N=35;
static AtomicInteger result = new AtomicInteger(0), pendingTasks = new AtomicInteger(1);
static ExecutorService executor;
public static void main(String[] args) {
int nThreads=2;
System.out.println("Number of threads = "+nThreads);
executor = Executors.newFixedThreadPool(nThreads);
Executable.inQueue = new AtomicInteger(nThreads);
long before = System.currentTimeMillis();
System.out.println("Fibonacci "+N+" is ... ");
executor.submit(new FibSimpler(N));
waitToFinish();
System.out.println(result.get());
long after = System.currentTimeMillis();
System.out.println("Duration: " + (after - before) + " milliseconds\n");
}
private static void waitToFinish() {
while (0 < pendingTasks.get()){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
}
class FibSimpler implements Runnable {
int N;
FibSimpler (int n) { N=n; }
#Override
public void run() {
compute();
MainSimpler.pendingTasks.decrementAndGet(); // see text
}
void compute() {
int n = N;
if (n <= 1) {
MainSimpler.result.addAndGet(n); // see text
return;
}
MainSimpler.executor.submit(new FibSimpler(n-1));
MainSimpler.pendingTasks.incrementAndGet(); // see text
N = n-2;
compute(); // similar to the F/J counterpart
}
}
Runtime (approximately):
1 thread : 11 seconds
2 threads: 19 seconds
4 threads: 19 seconds
Update:
I notice that even if I use one thread inside the executor service, the whole program will use all four cores of my machine (each core around 80% usage on average). This could explain why using more threads inside the executor service slows down the whole process, but now, why does this program use 4 cores if only one thread is active inside the executor service??
It might be related to the fact that the size of each "task" submitted
to the executor service is really small.
This is certainly the case and as a result you are mainly measuring the overhead of context switching. When n == 1, there is no context switching and thus the performance is better.
But still it must be the same number also if I set nThreads to 1.
I'm guessing you meant 'to higher than 1' here.
You are running into the problem of heavy lock contention. When you have multiple threads, the lock on the result is contended all the time. Threads have to wait for each other before they can update the result and that slows them down. When there is only a single thread, the JVM probably detects that and performs lock elision, meaning it doesn't actually perform any locking at all.
You may get better performance if you don't divide the problem into N tasks, but rather divide it into N/nThreads tasks, which can be handled simultaneously by the threads (assuming you choose nThreads to be at most the number of physical cores/threads available). Each thread then does its own work, calculating its own total and only adding that to a grand total when the thread is done. Even then, for fib(35) I expect the costs of thread management to outweigh the benefits. Perhaps try fib(1000).
While running each thread why does the countdown.getCount() always print '3' even after the previous thread has already called countdown.countDown() and reduced the Latch Count by 1?
I am kind of worndering how Java knows that the Latch Count has reached 0, so that it can release all the 3 threads.
import java.util.concurrent.CountDownLatch;
class b {
static final CountDownLatch countdown = new CountDownLatch(3);
public static void main(String[] args) {
for (int i = 0; i < 3; ++i) {
Thread t = new Thread() {
public void run() {
System.out.printf("Starting on %d other threads.\n",
countdown.getCount());
countdown.countDown();
System.out.printf("new on %d other threads.\n",
countdown.getCount());
try {
countdown.await(); // waits until everyone reaches this
// point
// System.out.println("Go again : "
// +countdown.getCount());
} catch (Exception e) {
}
}
};
t.start();
}
System.out.println("Go");
}
}
you are starting 3 threads in parallel. depending on how fast they start, they could all print "3" before any of the threads manages to call countDown() (at least for the "Starting on..." line). the "new on ..." line, however, should print out some range of numbers between 2 and 0.
It's absolutely possible that all three threads print "Starting on 3.." as the threads run in parallel, and the count doesn't change until a thread executed countDown(). To really understand what's going on, I suggest you prepend System.nanoTime() and thread name before your print statements as below:
...
Thread t = new Thread("Thread-" + i) {
...
System.out.printf("%d> %s: Starting on %d other threads.\n", System.nanoTime(), getName(), countdown.getCount());
countdown.countDown();
System.out.printf("%d> %s: new on %d other threads.\n", System.nanoTime(), getName(), countdown.getCount());
Sometimes you'd get an output like below which may give you the impression that Thread-2 is disregarding Thread-1's call to countDown:
1407489646569321000> Thread-0: Starting on 3 other threads.
1407489646569324000> Thread-1: Starting on 3 other threads.
1407489646602463000> Thread-1: new on 1 other threads.
1407489646569513000> Thread-2: Starting on 3 other threads.
1407489646602107000> Thread-0: new on 2 other threads.
1407489646603275000> Thread-2: new on 0 other threads.
However, that is not the case, and we can verify the correct order of operations by looking at the timestamp. The mixup in the output is due to inherent unpredictability in thread scheduling, depending on which thread gets the cpu splice.
Having said that, they may not always print 3, depending on thread scheduling or delays. As an example, try putting a Thread.sleep(..) as shown below:
public static void main(String[] args) throws Exception {
for (int i = 0; i < 3; ++i) {
Thread t = new Thread() {
public void run() {
/* As before */
}
};
t.start();
Thread.sleep(100); // Artificial Delay
}
}
Now you should see different results like below:!
1407490223575404000> Thread-0: Starting on 3 other threads.
1407490223607879000> Thread-0: new on 2 other threads.
1407490223676233000> Thread-1: Starting on 2 other threads.
1407490223676818000> Thread-1: new on 1 other threads.
1407490223777623000> Thread-2: Starting on 1 other threads.
1407490223778221000> Thread-2: new on 0 other threads.
Internally, the CountDownLatch maintains a first in, first out wait Queue (See. AbstractQueuedSynchronizer). The value of the count is synchronized, and the waiting threads are only released when the count becomes 0 or someother thread interrupts the waiting thread. This is the mechanism used by the latch to keep track of when all the threads have arrived at the latch.
If you're interested in understanding the latch in the context of testing, checkout http://razshahriar.com/2014/08/testing-asynchronous-code-in-java-with-countdownlatch/
Hope this helps clarify your investigation of the Program behaviour.