A thread can use Object.wait() to block until another thread calls notify() or notifyAll() on that object.
But what if a thread wants to wait until one of multiple objects is signaled? For example, my thread must wait until either a) bytes become available to read from an InputStream or b) an item is added to an ArrayList.
How can the thread wait for either of these events to occur?
EDIT
This question deals with waiting for multiple threads to complete -- my case involves a thread waiting for one of many objects to be singnaled.
You are in for a world of pain. Use a higher level abstraction, such as a blocking message queue, from which the thread can consume messages such as 'more bytes available' or 'item added'.
They could all use the same mutex. You consumer is waiting on that mutex, the both other notify on that mutex when the first can proceed.
A thread cannot wait on more than one object at a time.
The wait() and notify() methods are object-specific. The wait() method suspends the current thread of execution, and tells the object to keep track of the suspended thread. The notify() method tells the object to wake up the suspended threads that it is currently keeping track of.
Useful link : Can a thread call wait() on two locks at once in Java (6) ?
Little late, but it's a very interesting question!
It would seems that you can indeed wait for multiple conditions, with the same performance, and no extra threads; It's just a matter of defining the problem! I took the time to write a more detailed explanation within the commits of the code bellow. By request I will extract the abstraction:
So in fact waiting on multiple objects, is the same as waiting on multiple conditions. But the next step is to merge your sub-conditions into a -net- condition a -single condition-. And when any component of the condition would cause it to become true you flip a boolean, and notify the lock (like any other wait-notify condition).
My approach:
For any condition, it can only result in two values (true and false). How that value is produced is irrelevant. In your case your "functional condition" is when either one of two values is true: (value_a || value_b). I call this "functional condition" the "Nexus-Point". If you apply the perspective that any complex condition -no matter how complex-, always yields a simple result (true or false), then what you're really asking for is "What will cause my net condition to become true?" (Assuming the logic is "Wait until true"). Thus, when a thread causes a component of your condition to become true (setting value_a, or value_b to true, in your case), and you know it'll cause your desired -net- condition to be met, then you can simplify your approach to a classical ( in that it flips a single boolean-flag, and releases a lock). With this concept, you can apply a object-ordinate approach to help aid the clarity of your overall logic:
import java.util.HashSet;
import java.util.Set;
/**
* The concept is that all control flow operation converge
* to a single value: true or false. In the case of N
* components in which create the resulting value, the
* theory is the same. So I believe this is a matter of
* perspective and permitting 'simple complexity'. for example:
*
* given the statement:
* while(condition_a || condition_b || ...) { ... }
*
* you could think of it as:
* let C = the boolean -resulting- value of (condition_a || condition_b || ...),
* so C = (condition_a || condition_b || ...);
*
* Now if we were to we-write the statement, in lamest-terms:
* while(C) { ... }
*
* Now if you recognise this form, you'll notice its just the standard
* syntax for any control-flow statement?
*
* while(condition_is_not_met) {
* synchronized (lock_for_condition) {
* lock_for_condition.wait();
* }
* }
*
* So in theory, even if the said condition was evolved from some
* complex form, it should be treated as nothing more then if it
* was in the simplest form. So whenever a component of the condition,
* in which cause the net-condition (resulting value of the complex
* condition) to be met, you would simply flip the boolean and notify
* a lock to un-park whoever is waiting on it. Just like any standard
* fashion.
*
* So thinking ahead, if you were to think of your given condition as a
* function whos result is true or false, and takes the parameters of the states
* in which its comprised of ( f(...) = (state_a || state_b && state_c), for example )
* then you would recognize "If I enter this state, in which this I know would
* cause that condition/lock to become true, I should just flip the switch switch,
* and notify".
*
* So in your example, your 'functional condition' is:
* while(!state_a && !state_b) {
* wait until state a or state b is false ....
* }
*
* So armed with this mindset, using a simple/assertive form,
* you would recognize that the overall question:
* -> What would cause my condition to be true? : if state_a is true OR state_b is true
* Ok... So, that means: When state_a or state_b turn true, my overall condition is met!
* So... I can just simplify this thing:
*
* boolean net_condition = ...
* final Object lock = new Lock();
*
* void await() {
* synchronized(lock) {
* while(!net_condition) {
* lock.wait();
* }
* }
* }
*
* Almighty, so whenever I turn state_a true, I should just flip and notify
* the net_condition!
*
*
*
* Now for a more expanded form of the SAME THING, just more direct and clear:
*
* #author Jamie Meisch
*/
public class Main {
/**
*
* The equivalent if one was to "Wait for one of many condition/lock to
* be notify me when met" :
*
* synchronized(lock_a,lock_b,lock_c) {
* while(!condition_a || !condition_b || !condition_c) {
* condition_a.wait();
* condition_b.wait();
* condition_c.wait();
* }
* }
*
*/
public static void main(String... args) {
OrNexusLock lock = new OrNexusLock();
// The workers register themselves as their own variable as part of the overall condition,
// in which is defined by the OrNuxusLock custom-implement. Which will be true if any of
// the given variables are true
SpinningWarrior warrior_a = new SpinningWarrior(lock,1000,5);
SpinningWarrior warrior_b = new SpinningWarrior(lock,1000,20);
SpinningWarrior warrior_c = new SpinningWarrior(lock,1000,50);
new Thread(warrior_a).start();
new Thread(warrior_b).start();
new Thread(warrior_c).start();
// So... if any one of these guys reaches 1000, stop waiting:
// ^ As defined by our implement within the OrNexusLock
try {
System.out.println("Waiting for one of these guys to be done, or two, or all! does not matter, whoever comes first");
lock.await();
System.out.println("WIN: " + warrior_a.value() + ":" + warrior_b.value() + ":" + warrior_c.value());
} catch (InterruptedException ignored) {
}
}
// For those not using Java 8 :)
public interface Condition {
boolean value();
}
/**
* A variable in which the net locks 'condition function'
* uses to determine its overall -net- state.
*/
public static class Variable {
private final Object lock;
private final Condition con;
private Variable(Object lock, Condition con) {
this.lock = lock;
this.con = con;
}
public boolean value() {
return con.value();
}
//When the value of the condition changes, this should be called
public void valueChanged() {
synchronized (lock) {
lock.notifyAll();
}
}
}
/**
*
* The lock has a custom function in which it derives its resulting
* -overall- state (met, or not met). The form of the function does
* not matter, but it only has boolean variables to work from. The
* conditions are in their abstract form (a boolean value, how ever
* that sub-condition is met). It's important to retain the theory
* that complex conditions yeild a simple result. So expressing a
* complex statement such as ( field * 5 > 20 ) results in a simple
* true or false value condition/variable is what this approach is
* about. Also by centerializing the overal logic, its much more
* clear then the raw -simplest- form (listed above), and just
* as fast!
*/
public static abstract class NexusLock {
private final Object lock;
public NexusLock() {
lock = new Object();
}
//Any complex condition you can fathom!
//Plus I prefer it be consolidated into a nexus point,
// and not asserted by assertive wake-ups
protected abstract boolean stateFunction();
protected Variable newVariable(Condition condition) {
return new Variable(lock, condition);
}
//Wait for the overall condition to be met
public void await() throws InterruptedException {
synchronized (lock) {
while (!stateFunction()) {
lock.wait();
}
}
}
}
// A implement in which any variable must be true
public static class OrNexusLock extends NexusLock {
private final Set<Variable> vars = new HashSet<>();
public OrNexusLock() {
}
public Variable newVar(Condition con) {
Variable var = newVariable(con);
vars.add(var); //register it as a general component of or net condition // We should notify the thread since our functional-condition has changed/evolved:
synchronized (lock) { lock.notifyAll(); }
return var;
}
#Override
public boolean stateFunction() { //Our condition for this lock
// if any variable is true: if(var_a || var_b || var_c || ...)
for(Variable var : vars) {
if(var.value() == true) return true;
}
return false;
}
}
//increments a value with delay, the condition is met when the provided count is reached
private static class SpinningWarrior implements Runnable, Condition {
private final int count;
private final long delay;
private final Variable var;
private int tick = 0;
public SpinningWarrior(OrNexusLock lock, int count, long delay) {
this.var = lock.newVar(this);
this.count = count; //What to count to?
this.delay = delay;
}
#Override
public void run() {
while (state_value==false) { //We're still counting up!
tick++;
chkState();
try {
Thread.sleep(delay);
} catch (InterruptedException ignored) {
break;
}
}
}
/**
* Though redundant value-change-notification are OK,
* its best to prevent them. As such its made clear to
* that we will ever change state once.
*/
private boolean state_value = false;
private void chkState() {
if(state_value ==true) return;
if(tick >= count) {
state_value = true;
var.valueChanged(); //Our value has changed
}
}
#Override
public boolean value() {
return state_value; //We could compute our condition in here, but for example sake.
}
}
}
It appears that in your case you're waiting for "notifications" from two different sources. You may not have to "wait" (as in normal java synchronized(object) object.wait()) on those two objects per se, but have them both talk to a queue or what not (as the other answers mention, some blocking collection like LinkedBlockingQueue).
If you really want to "wait" on two different java objects, you might be able to do so by applying some of the principles from this answer: https://stackoverflow.com/a/31885029/32453 (basically new up a thread each to do a wait on each of the objects you're waiting for, have them notify the main thread when the object itself is notified) but it might not be easy to manage the synchronized aspects.
Lock in both cases over the same object. Call in case a) or in case b) notify() on the same object.
You can wait only on one monitor. So notifiers must notify this one monitor. There is no other way in this low level synchronization.
In order handle the termination of any thread from a given set without waiting for all of them to finish, a dedicated common Object (lastExited below) can be used as monitor (wait() and notify() in synchronized blocks). Further monitors are required for ensuring that at any time at most one thread is exiting (notifyExitMutex) and at most one thread is waiting for any thread to exit (waitAnyExitMonitor); thus the wait()/notify() pairs pertain always to different blocks.
Example (all process terminations are handled in the order the threads finished):
import java.util.Random;
public class ThreadMonitor {
private final Runnable[] lastExited = { null };
private final Object notifyExitMutex = new Object();
public void startThread(final Runnable runnable) {
(new Thread(new Runnable() { public void run() {
try { runnable.run(); } catch (Throwable t) { }
synchronized (notifyExitMutex) {
synchronized (lastExited) {
while (true) {
try {
if (lastExited[0] != null) lastExited.wait();
lastExited[0] = runnable;
lastExited.notify();
return;
}
catch (InterruptedException e) { }
}
}
}
}})).start();
}
private final Object waitAnyExitMutex = new Object();
public Runnable waitAnyExit() throws InterruptedException {
synchronized (waitAnyExitMutex) {
synchronized (lastExited) {
if (lastExited[0] == null) lastExited.wait();
Runnable runnable = lastExited[0];
lastExited[0] = null;
lastExited.notify();
return runnable;
}
}
}
private static Random random = new Random();
public static void main(String[] args) throws InterruptedException {
ThreadMonitor threadMonitor = new ThreadMonitor();
int threadCount = 0;
while (threadCount != 100) {
Runnable runnable = new Runnable() { public void run() {
try { Thread.sleep(1000 + random.nextInt(100)); }
catch (InterruptedException e) { }
}};
threadMonitor.startThread(runnable);
System.err.println(runnable + " started");
threadCount++;
}
while (threadCount != 0) {
Runnable runnable = threadMonitor.waitAnyExit();
System.err.println(runnable + " exited");
threadCount--;
}
}
}
Related
I am using a Thread to do some calculations related to the app that need to be done simultaneously but this Thread causes the FPS to drop (logically) and I wanted to know how to resolve the issue as the Thread is not doing any heavy calculations at all. Here is the code where I implement the Thread and the Thread itself.
incrementMass = new IncrementMass();
incrementMass.start();
// I added some extra functionality to the InputProcessor but I assume that is irrelevant
if(InputProcessor.isButtonUp() && InputProcessor.getButtonLetGo() == RIGHT && !isJustPressed) {
isJustPressed = true;
try {
incrementMass.join();
} catch(InterruptedException e) {
e.printStackTrace();
}
planets.add(new Planet(10, m, mouseOnWorld2.x, mouseOnWorld2.y));
} else if(Gdx.input.isButtonJustPressed(RIGHT)) {
isJustPressed = false;
incrementMass.restart();
}
The Thread:
/**
* Thread to increment the mass in a while loop.
*/
public class IncrementMass extends Thread {
/**
* Increments the mass when started.
*/
#Override
public void run() {
super.run();
while(Gdx.input.isButtonPressed(Input.Buttons.RIGHT)) {
MainScreen.m += 100;
System.out.println(MainScreen.m);
}
}
/**
* Resets the mass so the whole thing starts over (for the creation of a new planet)
*/
public void restart() {
MainScreen.m = 100000;
}
}
All this is called in the render() function of my Screen by the way.
I have one idea as to what is causing this: Every frame I create a new Thread which is not optimal but everything else I tried failed to actually perform my calculations correctly. It definitely solves the FPS problem to have the initiation of the Thread and the ´start()´ function in the constructor of my Screen but that for some reason messes with the incrementing of the mass and makes it a fixed value: the value I reset it to in ´restart()´
I've been trying to solve this but I'm baffled so here I am.
As said in the comment, there was no function for isButtonJustUp() which made it not be able to run sequentially. Therefore I made a Thread so that it was sequential which is not a good implementation of Threads. I've come up with a solution:
if(Gdx.input.isButtonPressed(RIGHT)) {
m += 100;
} else if(InputProcessor.isButtonJustUp() && InputProcessor.getButtonLetGo() == RIGHT) {
planets.add(new Planet(10, m, mouseOnWorld2.x, mouseOnWorld2.y));
m=0;
}
I haven't made isButtonJustUp() yet but it is the best way rather than implementing an unnecessary Thread.
I am trying to understand a particular detail in ReentrantLock::lock method. I am looking at it and seeing it as:
final void lock() {
if (!initialTryLock()) {
acquire(1);
}
}
So first it tries this method : initialTryLock (I will look in NonfairSync), which does this:
it does a compareAndSwap(0, 1), meaning if no one holds the lock (0) and I can grab it (1), I hold the lock now.
if the above fails, it checks if the thread requesting the lock is the owner already.
if that fails it returns false, meaning I could not acquire the lock.
Let's assume the above failed. It then goes on and calls acquire in AbstractQueuedSynchronizer:
public final void acquire(int arg) {
if (!tryAcquire(arg))
acquire(null, arg, false, false, false, 0L);
}
It calls tryAcquire first in NonfairSync:
protected final boolean tryAcquire(int acquires) {
if (getState() == 0 && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
You can see that it tries to acquire the lock again, though the initialTryLock already failed. In theory, this tryAcquire could have simply returned false, right?
I see this as a potential retry, because between the calls of initialTryLock and tryAcquire, the lock might have been released. The benefit of this might be that because the next operation (after tryAcquire) fails, is the expensive enqueue of this thread. So I guess this makes sense (to retry) because of that?
Just to add to the answer above.
tryAcquire could have simply returned false, right?
No.
This implementation:
boolean tryAcquire(int acquires) {
return false;
}
would break the work of AbstractQueuedSynchronizer.
The reason is that tryAcquire() is the only way to take the lock in AbstractQueuedSynchronizer.
Even acquire() in the end uses tryAcquire().
So if tryAcquire() always returned false then acquire() would never acquire the lock.
And acquire() is used when several threads contend for the lock.
initialTryLock() contains reentrancy functionality:
javadoc:
/**
* Checks for reentrancy and acquires if lock immediately
* available under fair vs nonfair rules. Locking methods
* perform initialTryLock check before relaying to
* corresponding AQS acquire methods.
*/
abstract boolean initialTryLock();
source code in NonfairSync:
final boolean initialTryLock() {
Thread current = Thread.currentThread();
if (compareAndSetState(0, 1)) { // first attempt is unguarded
setExclusiveOwnerThread(current);
return true;
} else if (getExclusiveOwnerThread() == current) {
int c = getState() + 1;
if (c < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(c);
return true;
} else
return false;
}
Here:
the 1st if checks if the lock is taken (and takes the lock if it is free)
the 2nd if checks if the taken lock belongs to the current thread — this is the reentrancy logic.
tryAcquire() must be implemented by any class extending AbstractQueuedSynchronizer
what the method must do is described in its javadoc in AbstractQueuedSynchronizer
/**
* Attempts to acquire in exclusive mode. This method should query
* if the state of the object permits it to be acquired in the
* exclusive mode, and if so to acquire it.
* ...
*/
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
implementation in NonfairSync does exactly that (and doesn't contain reentrancy functionality):
/**
* Acquire for non-reentrant cases after initialTryLock prescreen
*/
protected final boolean tryAcquire(int acquires) {
if (getState() == 0 && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
Scenario - Trying to achieve the result with sleep() and interrupt(); which
would have been otherwise done by wait() and notifyAll()
Question - I know this way is not preferred. Can you guys please let me know what is wrong in doing like this in this below
scenario.
One reason is notifyAll() notify all threads looking for the lock on that object. But with interrupt()
we have the invoke interrupt on each waiting thread explicitly.
Other reason is that a different thread cannot change the object state. Here the initial thread itself make
food=true on catching an InterruptedException. But what is wrong with that?
/**
* Objective of this program:
*
* I was thinking, why can't we achieve the guarded block with Sleep and Interrupt,
* why only with wait and notify..
*
* Wait releases lock; while Sleep does not . But both suspend the execution.
* So if you are synchronizing on the object, then we cannot have the second thread
* to modify the object state due the lock on the object, and the second thread cannot acquire it.
*
* So I did a explicit interrupt on the first thread.
*
*/
/**
*
* One person ask if he has something to eat polling the "food" variable.
* Another person updates the shared variable food.
*
* food = true means the first person can start eating. food = false means he
* has to wait and poll the value until food is available(food = true). This is
* not a producer-consumer problem.
*
*/
public class _17GuardedBlockWithSleep_Interrupt_Badcase {
static class Person {
volatile boolean food;
public boolean isFood() {
return food;
}
public void setFood(boolean food) {
this.food = food;
}
String name;
Person(String name) {
this.name = name;
}
/*
* Sloppy/Bad way of implementation making it pause execution until it
* gets interrupted. An interruption alone does not mean food is
* available. May be interrupt was called by someone else who does not
* provide food. So check the condition too.
*
* Through sleep(), the execution is paused. CPU is free to take other
* tasks, The lock on object is NOT released so other threads CANNOT
* acquire the lock on the object.
*/
// Guarded Block
public synchronized void eatFood() {
while (!isFood()) {
// food is currently unavailable. I'm waiting..
try {
/**
* Ideally we do wait() and notifyAll() in such a scenario. I am
* trying with Sleep and Interrupt.
*/
Thread.sleep(1000000000);
} catch (InterruptedException e) {
this.setFood(true);// it's not some other thread that provide food. it's itself!
System.out.println("eatFood() caught InterruptedException");
// e.printStackTrace();
}
}
// if control comes here, then it means food is available
System.out.println("got the food.. yummyy..thanks!");
}
public synchronized void provideFood(Thread t) {
this.setFood(true); // this refers to current object. In this case, the
// 'kuttappan' object
// interrupt the first thread
t.interrupt();
}
}
public static void main(String[] args) {
final Person kuttappan = new Person("Kuttappan");
Runnable runnable1 = new Runnable() {
#Override
public void run() {
/*
* if kuttappan is not already defined as final, you get an error
* "Cannot refer to a non-final variable kuttappan inside an inner class defined in a different method"
*/
kuttappan.eatFood();
/*
* thread will try to acquire the lock on 'kuttappan' object when it
* invokes the synchronized method.
*/
}
};
final Thread t = new Thread(runnable1, "thread1");
t.start();
// someone is needed to make the food available for kuttappan.
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5000); // 5 seconds
t.interrupt(); // MY IMPORTANT LINE
// kuttappan.provideFood(t);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
/**
* OUTPUT:
*
* Observe the line commented as "MY IMPORTANT LINE"
*
* If you do 'kuttappan.provideFood(t);' then the program Keeps on running. no
* output, because
*
* The second thread cannot get into provideFood() of kuttappan object because
* the first thread has not released the lock on the object!
*
* But if you do t.interrupt(); the thread is interrupted and the program
* behaves as expected.
*/
From here: Difference between wait() and sleep()
"Sleeping a Thread does not release the locks it holds, while waiting releases the lock on the object that wait() is called on."
So in your case it appears that if there is no food available it's impossible for another thread to go in and make food available.
It also appears that even if you call t.interrupt(), the first thread will just see that there isn't any food, so it'll sleep again. I could very well be interpreting this incorrectly though... working on this...
Never mind, I misread part of your code. I think part of the problem is that you rely on the original thread itself to do the work that the second thread should have done. So really you're not doing much better than having a single thread add food then consume it...
Its a poor choice because you are counting on one thread catching an interrupted exception every time. Exceptions are a high overhead mechanism for IPC. There may be more reasons but this is enough to get it yanked out of production code.
I think in your scenario producer thread should always have reference to consumer thread in order to interrupt() it and give it possibility to process "event".
If you use wait()/notify() you do not need threads to know each other, all you need is a synchronization point - object that you wait/notify on. Also you can share this object with as many threads as you want. So at the end producer thread does not care who exactly waits for the resource, it only needs to send signal that resource is available.
I thought that using ThreadPoolExecutor we can submit Runnables to be executed either in the BlockingQueue passed in the constructor or using the execute method.
Also my understanding was that if a task is available it will be executed.
What I don't understand is the following:
public class MyThreadPoolExecutor {
private static ThreadPoolExecutor executor;
public MyThreadPoolExecutor(int min, int max, int idleTime, BlockingQueue<Runnable> queue){
executor = new ThreadPoolExecutor(min, max, 10, TimeUnit.MINUTES, queue);
//executor.prestartAllCoreThreads();
}
public static void main(String[] main){
BlockingQueue<Runnable> q = new LinkedBlockingQueue<Runnable>();
final String[] names = {"A","B","C","D","E","F"};
for(int i = 0; i < names.length; i++){
final int j = i;
q.add(new Runnable() {
#Override
public void run() {
System.out.println("Hi "+ names[j]);
}
});
}
new MyThreadPoolExecutor(10, 20, 1, q);
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*executor.execute(new Runnable() {
#Override
public void run() {
System.out.println("++++++++++++++");
}
}); */
for(int i = 0; i < 100; i++){
final int j = i;
q.add(new Runnable() {
#Override
public void run() {
System.out.println("Hi "+ j);
}
});
}
}
}
This code does not do absolutely anything unless I either uncomment the executor.prestartAllCoreThreads(); in the constructor OR I call execute of the runnable that prints System.out.println("++++++++++++++"); (it is also commented out).
Why?
Quote (my emphasis):
By default, even core threads are initially created and started only
when new tasks arrive, but this can be overridden dynamically using
method prestartCoreThread() or prestartAllCoreThreads(). You probably
want to prestart threads if you construct the pool with a non-empty
queue.
Ok. So my queue is not empty. But I create the executor, I do sleep and then I add new Runnables to the queue (in the loop to 100).
Doesn't this loop count as new tasks arrive?
Why doesn't it work and I have to either prestart or explicitely call execute?
Worker threads are spawned as tasks arrive by execute, and these are the ones that interact with the underlying work queue. You need to prestart the workers if you begin with a non-empty work queue. See the implementation in OpenJDK 7.
I repeat, the workers are the ones that interact with the work queue. They are only spawned on demand when passed via execute. (or the layers above it, e.g. invokeAll, submit, etc.) If they are not started, it will not matter how much work you add to the queue, since there is nothing checking it as there are no workers started.
ThreadPoolExecutor does not spawn worker threads until necessary or if you pre-empt their creation by the methods prestartAllCoreThreads and prestartCoreThread. If there are no workers started, then there is no way any of the work in your queue is going to be done.
The reason adding an initial execute works is that it forces the creation of a sole core worker thread, which then can begin processing the work from your queue. You could also call prestartCoreThread and receive similar behavior. If you want to start all the workers, you must call prestartAllCoreThreads or submit that number of tasks via execute.
See the code for execute below.
/**
* Executes the given task sometime in the future. The task
* may execute in a new thread or in an existing pooled thread.
*
* If the task cannot be submitted for execution, either because this
* executor has been shutdown or because its capacity has been reached,
* the task is handled by the current {#code RejectedExecutionHandler}.
*
* #param command the task to execute
* #throws RejectedExecutionException at discretion of
* {#code RejectedExecutionHandler}, if the task
* cannot be accepted for execution
* #throws NullPointerException if {#code command} is null
*/
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);
}
A BlockingQueue is not a magic thread dispatcher. If you submit Runnable objects to the queue and there are no running threads to consume those tasks, they of course will not be executed. The execute method on the other hand will automatically dispatch threads according to the thread pool configuration if it needs to. If you pre-start all of the core threads, there will be threads there to consume tasks from the queue.
I have a situation where I have a callback that I want to execute once. For the sake of argument let's say it looks like this:
final X once = new X(1);
Runnable r = new Runnable() {
#Override public void run() {
if (once.use())
doSomething();
}
}
where X is some concurrent object with the following behavior:
constructor: X(int N) -- allocates N use permits
boolean use(): If there is at least 1 use permit, consume one of them and return true. Otherwise return false. This operation is atomic with respect to multiple threads.
I know I can use java.util.concurrent.Semaphore for this, but I don't need the blocking/waiting aspect of it, and I want this to be a one-time use thing.
AtomicInteger doesn't look sufficient unless I do something like
class NTimeUse {
final private AtomicInteger count;
public NTimeUse(int N) { this.count = new AtomicInteger(N); }
public boolean use() {
while (true)
{
int n = this.count.get();
if (n == 0)
return false;
if (this.count.compareAndSet(n, n-1))
return true;
}
}
and I feel queasy about the while loop.
CountDownLatch won't work, because the countDown() method has no return value and can't be executed atomically w/r/t getCount().
Should I just use Semaphore or is there a more appropriate class?
In the case of single permit you can use AtomicBoolean:
final AtomicBoolean once = new AtomicBoolean(true);
Runnable r = new Runnable() {
#Override public void run() {
if (once.getAndSet(false))
doSomething();
}
}
If you need many permits, use your solution with compareAndSet(). Don't worry about the loop, getAndIncrement() works the same way under the cover.
yes. AtomicInteger is non-blocking. You can use getAndDecrement().
You can use something like
if(counter.getAndDecrement() > 0) {
// something
} else {
counter.set(0);
}
This will work provided you don't call it two billion times between the decrement and the set. i.e. you would need to have two billion threads stop between these two statements.
Again you can use AtomicLong for extra paranoia.
// This implements an unfair locking scheme:
while ( mayContinue() ) {
// acquire the permit and check if it was legally obtained
if ( counter.decrementAndGet() > 0 )
return true;
// return the illegally acquired permit
counter.incrementAndGet();
}
return false;
Setting the counter back to zero if you discover the permit was illegally obtained creates a race condition when another thread releases a permit. This only works for situations where there are 2 or 3 threads at most. Some other backoff or latching mechanism needs to be added if you have more.