I glanced at execute method of ThreadPoolExecutor class. This seems to be very short and simple:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
But nothing seems to be happening if the the condition poolSize >= corePoolSize is satisfied!
Because of if the first part of a ORcondition is true, the second won't be executed:
if (true || anyMethodWillNotBeExecuted()) { ... }
According to the rules for thread creation, here also is maximumPoolSize. And in case if the number of threads is equal (or greater than) the corePoolSize and less than maxPoolSize the new thread should be created for task or task should be added to queue.
So why in case when poolSize greater than or equals to corePoolSize nothing should happen?..
addIfUnderCorePoolSize will create a new "core" thread for this executor.
If number of threads in the executor (poolSize) is already greater than or equal to number of "core" threads (corePoolSize), then obviously there is no need to create more "core" threads.
Maybe expanding OR condition will be a bit clearer:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
if (poolSize >= corePoolSize) {
// there are enough core threads
// let's try to put task on the queue
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
} else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
} else if (addIfUnderCorePoolSize(command)) {
// there was not enough core threads, so we started one
// the task is being executed on a new thread, so there's nothing else to be done here
return;
} else {
// there are enough core threads
// but we could not start a new thread
// so let's try to add it to the queue
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
} else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
Related
I found following source code in LinkedBlockingQueue
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
notEmpty.await();
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
The await method release the lock and after it is signaled, in while loop again, seems it does not have the lock. And in notEmpty<Condition> it specifies that IllegalMonitorStateException would be thrown if not holding the lock during calling await.
This confused me.. Does it hold the lock or not eventually?
of course It holds the lock.to judge whether the data can be token from queue, it uses loop.
when the queue is still empty,it should await again until its notified and the queue count is not zero .
I'm little confused with tasks in Java multithreading.
Namely, I've 15 objects, which implements Callable and i'm submitting it by ExecutorService. Each Callable has its own progress bar with is updating in for loop with setProgress method.
I want to show 3 of 15 callables which will finish their job in first, second and third position by getting their names and setting it to labels on my scene. Of course each callable has different working time.
I created Task and i'm starting it in new thread and iterating over list of future tasks from my ExecutorService.
The problem is that my labels aren't visible until first element of the future list is true (until first thread is finished). I have really no idea why and i would be very grateful for your help.
public void startButtonClicked() {
Task task = new Task<Void>() {
#Override
public Void call() {
int i = 0;
while (i < 3) {
for (Future<Boolean> future : futures) {
try {
if (future.get() == true && i == 0) {
labelFirst.setVisible(true);
i++;
}
if (future.get() == true && i == 1) {
labelSecond.setVisible(true);
i++;
}
if (future.get() == true && i == 2) {
labelThird.setVisible(true);
i++;
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
return null;
}
};
for (Callable c : callables) {
futures.add(executorService.submit(c));
}
new Thread(task).start();
executorService.shutdown();
}
In my ideal solution each label will become visible when their callable will finish, so labelSecond should appear some time after labelFirst.
It's my call method in my callable:
public Boolean call() {
double raceTime = ThreadLocalRandom.current().nextDouble(45.0, 60.0);
try {
for (double i = 0; i < raceTime; i += 0.01) {
TimeUnit.MILLISECONDS.sleep(1);
progressBar.setProgress(i / raceTime);
}
} catch (ParseException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
EDIT:
With checking future.isDone() and little changes it works as i wished.
public void startButtonClicked() {
Task task = new Task<Void>() {
#Override
public Void call() {
int i = 0;
while (i < 3) {
i = 0;
for (Future<Boolean> future : futures) {
if (future.isDone() == true) i++;
if (i == 1) {
labelFirst.setVisible(true);
labelFirstCyclistName.setVisible(true);
}
if (i == 2) {
labelSecond.setVisible(true);
labelSecondCyclistName.setVisible(true);
}
if (i == 3) {
labelThird.setVisible(true);
labelThirdCyclistName.setVisible(true);
}
}
}
return null;
}
};
for (Cyclist c : cyclists) {
futures.add(executorService.submit(c));
}
new Thread(task).start();
executorService.shutdown();
}
The problem is that my labels aren't visible until first element of
the future list is true (until first thread is finished). I have
really no idea why and i would be very grateful for your help.
According to the documentation of Future#get
Waits if necessary for the computation to complete, and then retrieves
its result.
Here is your code - pay special attention to a line containing future.get():
public Void call() {
int i = 0;
while (i < 3) {
for (Future<Boolean> future : futures) {
try {
if (future.get() == true && i == 0) {
During the first iteration of the loop the first future is retrieved from futures, and then future.get() stops the execution of the loop and waits (holds) until execution of this first future (the first thread) will finish and will return a result.
Then the loop continues and LabelX..setVisible(true); are called making labels visible.
I need to override execute method of executor where I need to change the behavior that threads more than core pool size will be created only when queue is full.
However in real time applications this behavior is undesirable as it can lead to unending wait of task present in queue.
I have changed the execute method as below:
public void execute(Runnable command)
{
System.out.println("ActiveCount : " + getActiveCount() + " PoolSize : " + getPoolSize()
+ " QueueSize : " + getQueue().size() +" Idle Threads : " +(getPoolSize()-getActiveCount()));
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
else if (isRunning(c) && workQueue.offer(command))
{
int recheck = ctl.get();
if (getActiveCount() < workerCountOf(recheck) && isRunning(recheck) && workQueue.offer(command)) {
return;
}
if (addWorker(command, false)) {
return;
}
else if (! isRunning(recheck) && remove(command))
{
reject(command);
}
else if (workerCountOf(recheck) == 0)
{
addWorker(null, false);
}
}
else
{
reject(command); // add task to the queue
}
}
Trying to achieve:
CoreThreads -> Non-CoreThreads -> Queue instead of CoreThreads -> Queue -> Non-CoreThreads.
I dont understand why you need to change execute method, I think, max pool size should not be preferred over queue, as I can see in you code.
I had same problem and you can follow the link :
click to follow the thread.
I feel this should be you last choice, try something else first.
I have a question about synchronized blocks and multithreading. I have an "alternate" situation in which two synchronized blocks should be executed before and after a non-synchronized block, and such blocks should not interfere each other.
Here is (a portion of) the code:
boolean calculate = false;
synchronized(this){
Double oldSim = struct.get(pair);
if(oldSim == null || oldSim < maxThreshold)
calculate = true;
}
if(calculate)
{
// This part should be parallel
Double newSim = calculateSimilarity(...);
synchronized(this){
if(newSim > minThreshold && (oldSim == null || newSim > oldSim))
struct.put(pair, newSim);
}
}
The problem is that, in this way, different threads could execute the first sync block, while another thread could execute the second sync block. So, I though this solution:
int maxThreshold = 1.0;
if(checkAndwriteSimilarity(pair, null, false))
{
Double newSim = calculateSimilarity(table, pKey1, pKey2, pKey1Val, pKey2Val, c);
checkAndwriteSimilarity(pair, newSim, true);
}
private synchronized boolean checkAndwriteSimilarity(Pair pair, Double newSim, boolean write)
{
Double oldSim = struct.get(pair);
if(!write)
{
if(oldSim == null || oldSim < maxThreshold)
return true;
else
return false;
}
else
{
if(newSim > minThreshold && (oldSim == null || newSim > oldSim))
struct.put(pair, newSim);
return true;
}
}
Do you think it is the most correct solution? I sincerely do not like such method a lot ...
Do you have alternative solutions to suggest?
Thank you
Code is too large, so I'll just copy the part that is problematic.
This is run() method in one class:
public void run(){
try{
sleep(1000);
while(true){
synchronized(space){
if(end)
return;
if(space[X][Y] == null)
break;
if(((Ship)space[X][Y]).isDestroyed){
destroy();
break;
}
if(isThereAnyShipsInTheArea() != 0){
if(team != ((Ship)space[X][Y + isThereAnyShipsInTheArea()]).team){
fight(isThereAnyShipsInTheArea());
}
}
else
move();
if(isDestroyed){
destroy();
break;
}
}
}
}
catch(InterruptedException ie){
System.out.println("Interrupted exception!");
}
}
This is simulation of Star Trek. Variable team represends to which team the ship belongs. Varable isDestroyed is true if the ship is destroyed in battle or crash when moving.
isThereAnyShipsInTheArea() - ship is within range if the distance one or two.
space is matrix whit dimensions [90]x[90].
I think problem is in run method, but I'll give you some other methods.
private int isThereAnyShipsInTheArea(){
if(space[X][Y - 2] instanceof Ship && ((Ship)space[X][Y - 2]).isDestroyed == false)
return -2;
if(space[X][Y - 1] instanceof Ship && ((Ship)space[X][Y - 1]).isDestroyed == false)
return -1;
if(space[X][Y + 1] instanceof Ship && ((Ship)space[X][Y + 1]).isDestroyed == false)
return 1;
if(space[X][Y + 2] instanceof Ship && ((Ship)space[X][Y + 2]).isDestroyed == false)
return 2;
return 0;
}
private synchronized void fight(int meet){
while(((Ship)svemir[X][Y]).isDestroyed == false && ((Ship)space[X][Y + meet]).isDestroyed == false){
if(((Ship)space[X][Y]).getProjectile() != 0){
((Ship)space[X][Y + meet]).setShield(((Ship)space[X][Y + meet]).getShield() - 1);
((Ship)space[X][Y + meet]).setWarp(((Ship)space[X][Y + meet]).getWarp() - 1);
((Ship)space[X][Y]).setProjectile(((Ship)space[X][Y]).getProjectile() - 1);
if(((Ship)space[X][Y + meet]).getShield() == 0 || ((Ship)space[X][Y + meet]).getWarp() == 0){
((Ship)space[X][Y + meet]).isDestroyed = true;
return;
}
}
if(((Ship)space[X][Y + meet]).getProjectile() != 0){
((Ship)space[X][Y]).setShield(((Ship)space[X][Y]).getShield() - 1);
((Ship)space[X][Y]).setWarp(((Ship)space[X][Y]).getWarp() - 1);
((Ship)space[X][Y + meet]).setProjectile(((Ship)space[X][Y + meet]).getProjectile() - 1);
if(((Ship)space[X][Y]).getShield() == 0 || ((Ship)space[X][Y]).getWarp() == 0){
this.isDestroyed = true;
return;
}
}
if(((Ship)space[X][Y]).getProjectile() == 0 && ((Ship)space[X][Y + meet]).getProjectile() == 0)
return;
}
}
To me you shouldn't do Thread.sleep() since it doesn't release any resources it grabs. Either schedule your task using ScheduledExecutorService or do wait() and yield() on an object monitor.
Your sleep is outside of your while(true) block, so instead of sleeping for a second every loop, you sleep once and then go into a tight loop.
Put the sleep at the end of the while(true) block, so you sleep once for every iteration of the loop. Ideally it should be just after the release of the synchronization on the space array.
Actually, full array scanning is far from ideal on finding items. Might want to look into keeping lists of items. Just to get an idea, a 1000x1000 array that has 20 items in it (space is big and mostly empty) will take 1,000,000 checks as you pass over the array, but if you reorganize your checks to be base on the items, you could probably get away with just 1000 or less checks.
For example, a list of ships:
for (Ship ship : ships) {
if (!ship.engaged()) {
ship.scanForEnemies();
}
if (ship.detectEnemies()) {
ship.attack();
}
}
might only have to loop through a dozen or fewer ships, checking a few hundred locations. If you are wondering how the above code works, in my example, the ship would have been constructed with a space array, that it kept a reference to.