Future task of ExecutorService not truly cancelling - java

I push my Futures from a ExecutorService into a hash map. Later, I may call cancel on Futures from within the hash map. Although the result is true, I later hit breakpoints within the Callable procedure, as if the Future cancel() had no effect. I think it might be a case of two different references here (even though the reference IDs are listed as the same when breakpointing), but was wondering if some experts could chime in. Here's what the code looks like:
ExecutorService taskExecutor = Executors.newCachedThreadPool();
Map <String, Future<Object>> results = new HashMap <String, Future<Object>>();
Future<Object> future = taskExecutor.submit(new MyProcessor(uid));
results.put(uid, future);
I allow processing to continue (it's a loop that submits tasks as they are passed in), and later I may attempt to cancel from an outside source by calling this method:
public static synchronized boolean cancelThread(String uid) {
Future<Object> future = results.get(uid);
boolean success = false;
if (future != null) {
success = (future.isDone() ? true : future.cancel(true));
if (success)
results.remove(uid);
}
return success;
}
But I still encounter a "non-cancelled" path within MyProcessor.call() after future.cancel() is called - i.e. it's not really being cancelled.
Where am I going wrong with this? Is there a better was to do this?

I later hit breakpoints within the Callable procedure, as if the Future cancel() had no effect.
Future.cancel(true) removes a job that is in the queue and not yet running but if the job is already running it does the equivalent of Thread.interrupt() on the thread running the job. This sets the interrupt bit on the thread and causes any sleep(), wait(), and some other methods to throw InterruptedException.
It is important to realize that it does not stop the thread. You need to actively check for the interrupt flag in your thread loop or properly handle InterruptedException.
See my SO answer here for more details: How to suspend thread using thread's id?

FutureTask :: boolean cancel(boolean mayInterruptIfRunning) will perform interrupt on current running thread.
FutureTask.java
public boolean cancel(boolean mayInterruptIfRunning) {
if (!(state == NEW &&
UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt(); ////////////HERE/////////////
} finally { // final state
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
return true;
}
JavaDoc says the below for interrupt
public void interrupt()
Interrupts this thread. Unless the current
thread is interrupting itself, which is always permitted, the
checkAccess method of this thread is invoked, which may cause a
SecurityException to be thrown.
If this thread is blocked in an invocation of the wait(), wait(long),
or wait(long, int) methods of the Object class, or of the join(),
join(long), join(long, int), sleep(long), or sleep(long, int), methods
of this class, then its interrupt status will be cleared and it will
receive an InterruptedException.
If this thread is blocked in an I/O operation upon an interruptible
channel then the channel will be closed, the thread's interrupt status
will be set, and the thread will receive a ClosedByInterruptException.
If this thread is blocked in a Selector then the thread's interrupt
status will be set and it will return immediately from the selection
operation, possibly with a non-zero value, just as if the selector's
wakeup method were invoked.
If none of the previous conditions hold then this thread's interrupt
status will be set.
Interrupting a thread that is not alive need not have any effect.
Throws: SecurityException - if the current thread cannot modify this
thread
To conclude; cancel of FutureTask has only impact if the thread is blocked (in an invocation of the wait(),...) else it is developer responsibility to check Thread.currentThread().isInterrupted() to quit; while performing non blocked operation.

Related

FutureTask get() method may distable LockSupport.park

i found FutureTask get() method may distable LockSupport.park in oracle jdk8
my code is :
ExecutorService service = Executors.newFixedThreadPool(1, (r) -> {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
});
Future<String> submit = service.submit(() -> {
TimeUnit.SECONDS.sleep(5);
System.out.println("exec future task..");
return "a";
});
System.out.println(submit.get());
LockSupport.park(new Object());
System.out.println("error,unPark");
}
i thoughtSystem.out.println("error,unPark");would not execute;but it did
exec future task..
a
error,unPark
for simulating thread schedule,I break point on FutureTask line 418
queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q);
step over fastly before print exec future task..
after print exec future task.. for a while , continue to execute ..
then skip LockSupport.park(new Object()); and print error,unPark
i think
1.FutureTask add getting thread(main) in waiters;
2.execution thread(the thread pool) finish the task,and unpark all waiters;
3.getting thread(main) read state and found task hash finished, then return result and skip executing FutureTask locksupport.park()
4.because unpark method was executed in futuretask,then can skip LockSupport.park(new Object());and print error,unPark
is it a bug?
The documentation does says:
Disables the current thread for thread scheduling purposes unless the permit is available.
If the permit is available then it is consumed and the call returns immediately; otherwise the current thread becomes disabled for thread scheduling purposes and lies dormant until one of three things happens:
Some other thread invokes unpark with the current thread as the target; or
Some other thread interrupts the current thread; or
The call spuriously (that is, for no reason) returns.
This method does not report which of these caused the method to return. Callers should re-check the conditions which caused the thread to park in the first place. Callers may also determine, for example, the interrupt status of the thread upon return.
The third bullet alone would be enough to tell you that you can’t assume that returning from park implies that the condition you’re waiting for has been fulfilled.
Generally, this tool is meant for code that can not assume atomicity for the operation that checks/induces the condition and the park/unpark call.
As the documentation concludes you have to re-check the condition after returning from park. Special emphasis on “re-”; since this implies that you might find out that the return from park was not due to your condition being fulfilled, you might have consumed an unpark that was not for you. This in turn implies, that you also must test the condition before calling park and not call it when the condition has been fulfilled already. But if you do this, you might skip a park when unpark has been called, so some subsequent park call will return immediately.
In short, even without “spurious returns”, you always have to test your specific condition before calling park and re-check the condition after returning from park, in a loop if you want to wait for the condition.
Note that most of it also applies to using wait/notify in a synchronized block or await/signal when owning a Lock. Both should be used with a pre-test loop for reliable results.

How does JVM notify a thread blocked by `join()`?

The join() method waits for a thread to die. it use wait to do this.
if (millis == 0) {
while (isAlive()) {
wait(0);
}
}
So when the thread exits, how can it notify threads in wait set.
I try to find code in JDK source code, but failed. Can anyone show me the relevant code snippets?
when a thread in wait set, it may check isAlive() so many times for its timeslice, is this a waste?
if isAlive() is false, it just return, that thread is already in wait set. Is the while(isAlive()) necessary?
I try to find code in JDK source code, but failed. Can anyone show me the relevant code snippets?
The pathname for the Thread class in the OpenJDK jdk8u source tree is jdk/src/share/classes/java/lang/Thread.java. The code for join() is below.
The native code where the notifyAll occurs is in Thread::exit in hotspot/src/share/vm/runtime/thread.cpp.
For other releases the paths may be different. (The find command is your friend.)
When a thread in wait set, it may check isAlive() so many times for its timeslice, is this a waste?
That is incorrect.
The "wait set" argument is incorrect. If the current thread can call isAlive() it is not in any wait set. It will only be in the "wait set" for the target Thread when it is in a wait(...) call. It is removed from the "wait set" when the current thread is notified.
To reiterate, a thread t1 is in the "wait set" of another thread t2 when t1 is executing t2.wait(...).
A wait(0) call means "wait until notified without a timeout". (It does NOT mean the same thing assleep(0) or yield()!) Therefore, this is not a busy loop.
The loop will usually go around zero or one time only. (But see the next part of my answer.)
If isAlive() is false, it just return, that thread is already in wait set. Is the while(isAlive()) necessary?
Your "wait set" logic is incorrect (as above).
The loop is necessary. It is possible for any application code that has a reference to the target Thread object to call Object.notify() on that it. That causes the wait(0) to return. But since this "wake up" is spurious, it is necessary to check that the target Thread has actually ended (by calling isAlive()) and maybe waiting again.
This could happen repeatedly ... if application code is doing something silly ... but it shouldn't.
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
Most of the implementation of Thread is in native code. That is where the notifyAll that wakes up the joining threads is made.
To answer your questions:
wait() is a native method and uses System code. There is no Java code for that.
wait() is not a means to wait for a Thread but to synchronize on a certain object. Wait() is the wrong method to pause a thread, you need to use sleep().
The counterpart of wait() is notify() or notifyAll(). This will wake up Threads which wait for the calling object. Wait() and notify are part of the Object.class and need a synchronization on the object.
A Thread is alive as long as its run method is executing. If you join a thread the calling thread will automatically halt.
If you want to let a thread wait then use Thread.sleep.
Thread t1 = new Thread(){
public void run(){
try {
sleep(5000);
} catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("I'm done");
}
}
t1.start();
//The calling thread will wait here for 5 sec.
t1.join();

Can a synchronized block/method be interrupted?

While I know the theoretical differences between Re-EntrantLocks and synchronized, I'm confused to the below point.
See this statement from an article on Javarevisited comparing synchronized and Lock objects:
One more worth noting difference between ReentrantLock and
synchronized keyword in Java is, ability to interrupt Thread while
waiting for Lock. In case of synchronized keyword, a thread can be
blocked waiting for lock, for an indefinite period of time and there
was no way to control that. ReentrantLock provides a method called
lockInterruptibly(), which can be used to interrupt thread when it is
waiting for lock. Similarly tryLock() with timeout can be used to
timeout if lock is not available in certain time period.
As per the above statement, I did try interrupting the Thread waiting() on synchronized method (i.e blocking wait) and it did throw an InterruptedException. But this behavior is contradictory with what is stated in the above statement.
// this method is called from inside run() method of every thread.
public synchronized int getCount() {
count++;
try {
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + " gets " + count);
} catch (InterruptedException e) {
e.printStackTrace();
}
return count;
}
....
....
t1.start();
t2.start();
t3.start();
t4.start();
t2.interrupt();
Here is the output that I got :
Thread 1 gets 1
Thread 4 gets 2
Thread 3 gets 3
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at locks.SynchronizedLockInterrupt.getCount(SynchronizedLockInterrupt.java:10)
at locks.SynchronizedLockInterrupt$2.run(SynchronizedLockInterrupt.java:35)
at java.lang.Thread.run(Unknown Source)
I'm confused if my example is not correct or the quoted statement about synchronized() is incorrect?
Without the rest of the code this question might not be fully answered.
What, I think, you're being confused with here is that you're seeing that, whilst the code would imply you cannot "interrupt" a thread that's blocked on a synchronized lock you are seeing that your count variable seems to be unaffected by the thread which is supposed to have entered into this method.
Important to note that you can technically "interrupt" a blocked thread, as in you can call interrupt() on it and this will set the interrupted flag. Just because a Thread has the interrupted flag set does not mean that it cannot execute any more code. Simply, when it get's to the next code that checks for an interrupted state, that code will likely throw an InterruptedException whilst clearing the flag at the same time. If the person catching the exception intends to do more work, it's their (almost moral) duty to re-set the flag or throw the same.
So, yes, in your example, you are catching the exception that has been thrown by .sleep() on entry, likely before the thread was sleep-ed, you then print the stack trace that proves that.
The outstanding question that might be causing confusion for you; why, then, did my count not increment if this code was allowed to run until the .sleep() method call?
The answer is that the count variable was incremented, you just didn't see the result.
synchronized in Java does not guarantee order and can lead to starvation so t2 just happened to be executed last and you never checked the count before you slept to see that it was already 3
So to answer your question, the documentation is correct and the behaviour is correct.
Interrupting a thread which is waiting "uninterruptedly" on a Lock , ReentrantLock or synchronized block will merely result in the thread waking up and seeing if it's allowed to take the lock yet, by whatever mechanism is in place in the defining lock, and if it cannot it parks again until it is interrupted again or told it can take the lock. When the thread can proceed it simply proceeds with its interrupted flag set.
Contrast to lockInterruptibly where, actually, if you are interrupted, you do not ever get the lock, and instead you "abort" trying to get the lock and the lock request is cancelled.
lock and lockInterruptibly can be mixed use on the same ReentrantLock as the lock will manage the queue and skip requests that were CANCELLED by a finally statement because they were interrupted when waiting on a lock.
In summary:
You can almost always interrupt a thread.
The interrupt flag is usually only cleared on a thread by code that documents that it clears the flag when throwing the InterruptedException , but not all code documents this (lockInterruptibly on ReentrantLock does, but not the same on AbstractQueuedSynchronizer which powers the lock).
Interrupting a thread has different behaviour depending on what it is doing at the time;
A parked thread will be un-parked and have it's flag set, usually then cleared
A thread waiting on a lock / synchronized block will eventually get into the code but with interrupted flag set
A thread waiting on a lockInterruptibly or a get on a future etc will be unparked and behave as documented, aborting the lock acquisition.
synchronized is an intrinsic lock which is beyond the control of JDK.
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.
In your example, you are actually interrupting the sleep as JDK doc mentions.
If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.
More details about how interrupt() works.
Many methods that throw InterruptedException, such as sleep, are designed to cancel their current operation and return immediately when an interrupt is received.
If have added a simple example to make it clear.
In your example you have already aquired the lock, see your stacktrace.
The code is self explaining.
The problem with synchronized is that it is no interruption point, whereas lock.lockInterruptibly() is. Note that lock.lock() is also not an interruption point.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Foo {
public static void main(String[] args) throws InterruptedException {
// for the example with synchronized
Object monitor = new Object();
// for the example with locks
Lock lock = new ReentrantLock();
// iam lazy, just use both lock and motitor for this example
Thread one = new Thread(() -> {
lock.lock();
try {
synchronized (monitor) {
System.out.println("Thread one entered monitor");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Thread one interrupted");
Thread.currentThread().interrupt();
}
}
} finally {
lock.unlock();
}
});
// uncomment to use the monitor object
// Thread two = new Thread(() -> {
// synchronized (monitor) {
// System.out.println("Thread two entered monitor");
// }
// });
Thread two = new Thread(() -> {
try {
lock.lockInterruptibly();
try {
System.out.println("Thread one entered lock");
} finally {
lock.unlock();
}
} catch (InterruptedException e) {
System.out.println("Thread two interrupted while waiting for lock");
Thread.currentThread().interrupt();
}
});
// start thread one
one.start();
// wait for the thread to start, too lazy to implement notifications
Thread.sleep(1000);
// start thread two
two.start();
// interrupting will wait until thread one finished
two.interrupt();
}
}
If you remove "Thread.sleep(3000)", your 'getCount()' method will not throw exception.
You can only interrupt a thread either in sleep or wait in case of Synchronised method
You're not interrupting the synchronization, you're interrupting the sleep().

Need to Stop or Terminate the Thread [duplicate]

This question already has answers here:
How to stop a java thread gracefully?
(6 answers)
Closed 8 years ago.
As i have Written a Simple Java Program to call Thread . below is my code
public class ThreadPoolForParallelExec {
public static void main(String args[]) {
ExecutorService service = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
service.submit(new Task(i));
}
service.shutdown();
}
}
final class Task implements Runnable {
private int taskId;
public Task(int id) {
this.taskId = id;
}
#Override
public void run() {
myclient.intializeAndConnectRemoteMachine(taskId);
Thread.currentThread().stop();
Thread.currentThread().isInterrupted();
}
}
However , I need to terminate the Executor or Thread . I tried Thread.currentThread().stop(); and
Thread.currentThread().stop(); both didnt work :( could you please suggets .
Generally speaking, to kill thread is a bad idea, and in fact, the latest Java specification deprecate that.
Instead, try to finish the thread gracefully within the thread itself. That is the consistent structure.
Just let the method end normally.
Then the Thread will be idle and the ExecutorService will shutdown afterwards.
I think you should call to interrupt() and then wait Threads to finish. Then you could do any actions without having threads running.
you can either use Thread.interrupt() or use volatile flag in run method and set it false when you want to stop thread.
#Override
public void run() {
while (running) {
try {
....
} catch (InterruptedException e) {
running = false;
}
}
}
while running is flag initialized as true.
for more details you can refer this link
The documentation for version 1.5 says:
interrupt
public void interrupt()
Interrupts this thread.
Unless the current thread is interrupting itself, which
is always permitted, the checkAccess method of this thread
is invoked, which may cause a SecurityException to be thrown.
If this thread is blocked in an invocation of the
wait(), wait(long), or wait(long, int) methods of the
Object class, or of the join(), join(long), join(long,
int), sleep(long), or sleep(long, int), methods of this
class, then its interrupt status will be cleared and it
will receive an InterruptedException.
If this thread is blocked in an I/O operation upon an
interruptible channel then the channel will be closed,
the thread's interrupt status will be set, and the
thread will receive a ClosedByInterruptException.
If this thread is blocked in a Selector then the
thread's interrupt status will be set and it will
return immediately from the selection operation,
possibly with a non-zero value, just as if the
selector's wakeup method were invoked.
If none of the previous conditions hold then this
thread's interrupt status will be set.
Throws:
SecurityException - if the current thread cannot modify this thread
Never use Thread.stop. It has been deprecated:
From JLS:
This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait
The good way to do it is to have the run() of the Thread guarded by a boolean variable and set it to true from the outside when you want to stop it.
Make sure you had made the guarding boolean field volatile to make sure the reading thread sees changes from the writing thread.

Java Thread - weird Thread.interrupted() and future.cancel(true) behaviour

I want to manage a list of Futures objects returned by my TaskExecutor.
I've something like this
List<Future<String>> list
void process(ProcessThis processThis) {
for ( ...) {
Future<String> future = taskExecutor.submit(processThis);
list.add(future)
}
}
void removeFutures() {
for(Future future : list) {
assert future.cancel(true);
}
ProcessThis is a task that implements Callable< String> and checks for Thread.interrupted() status
public String call() {
while (true) {
if (Thread.interrupted()) {
break;
}
doSomething();
}
}
Now the problem is that only a subset of the concurrent Threads is returning 'true' when Thread.interrupted() is called.
The assert in removeFutures() returns true for every future that is removed (I checked isDone() and isCompleted() as well.
The number of Threads that are interrupted is random. Over 15 running Threads sometimes 13 are interrupted, sometimes 2 ...
I really don't understand where's the issue. if I call future.cancel(true) and this returns true... and then I check Thread.interrupted (this is called only once), I expect this to return true as well.
Any idea of what am I missing?
I'm on build java 1.6.0_02-b05
Be aware that Thread.interrupted() returns the current interrupted status and then clears it, so all future invocations will return false. What you want is probably Thread.currentThread().isInterrupted().
Also be aware that future.cancel(true) will usually only return false if the task had already been completed or canceled. If it returns true, that is no guarantee that the task will actually be canceled.
What is happening in doSomething()? Its possible that a RuntimeException is escaping somewhere due to the interrupt. Do you have an UncaughtExceptionHandler set? If not, you'll need to pass a ThreadFactory to the Executor that will set the exception handler and log any missed exceptions.
At least, you should restore the interruption flag to make taskExecutor aware of the thread interruption:
public String call() {
while (true) {
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
break;
}
doSomething();
}
}
A potential problem that interrupts are often swallowed. So somewhere deep in doSomething() (or even in class loading), an interrupt may be caught by, say, wait() and then discarded by 'careless' code. Interrupts are evil, IMO.
It may be worth checking that all of you tasks are actually running at the time of the cancel.

Categories