There is a thread which connects to the server (HTTP) and waits for response or response timeout (server doesn't respond until it has data to return) in a loop. In case response returned a thread processing it.
On service stopping it is needed to stop/interrupt all threads but threads must finish response processing (in case a thread is processing and not just awaiting response).
Here is code example
public class WaitingResponseThread extends Thread {
static final int TIMEOUT = 4 * 1000;
static final int PROCESSING_DURATION = 2000;
private volatile boolean stopped = false;
private volatile boolean processing = false;
public void run() {
System.out.println("starting child thread");
while(!stopped) {
try {
// here a thread is awaiting server response (in real life response timeout is 400 sec)
// probably it is safe to interrupt the thread now
// emulating this with Thread.sleep()
System.out.println("awaiting response");
Thread.sleep(TIMEOUT);
processing = true;
// there is some job on response and we must allow it to finish the job
// again emulating delay with Thread.sleep()
Thread.sleep(PROCESSING_DURATION);
processing = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("ending child thread");
}
public void setStopped(boolean stopped) {
this.stopped = stopped;
}
public boolean isProcessing() {
return processing;
}
public static void main(String[] args) {
WaitingResponseThread t = new WaitingResponseThread();
// starting thread, it sends a request and waits for a response
t.start();
try {
Thread.sleep(1);
// let's allow the thread to finish normally in case it is processing response
t.setStopped(true);
System.out.println("awaiting child thread to get response");
Thread.sleep(TIMEOUT + 1);
// let's allow the thread to finish processing
while(t.isProcessing()) {
System.out.println("processing");
Thread.sleep(500);
}
// we can't wait for 400sec until the next loop check
// so as the thread is sleeping we just interrupting it
if(t.isAlive()) {
System.out.println("killing");
t.interrupt();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ending main thread");
}
}
Is this "interrupt" method good? Is there another way not to wait as long as timeout and not to lose data being processed?
This
while(t.isProcessing()) {
System.out.println("processing");
Thread.sleep(500);
}
is a form of polling. You should avoid polling at all costs. If possible, use a form of delegation where the callee notifies the caller when it is done processing.
Other than that, I'm pretty sure interrupting a thread is something you also rarely want to do, but that the way you're doing it is fine if you have to do it anyway.
The Thread class has a few functions that you can use when interrupting.
Catching an InterruptionException
Using the method isInterrupted() (not static)
Using the method interrupted() (static)
Checking interrupted() or isInterrupted() and then throw new InterruptedException()
With these you can probably make your thread finish the current job before killing it, probably within the catch clause.
Related
So I am attempting to start a new thread from within a thread.
i.e.
function(update):
under certain conditions:
add a new thread running same service as current
Ideally I would like the new thread to run and my current thread to continue executing.
Instead, a new thread is created but only when it is completed does my host thread continue again.
Ideally I need it to execute concurrently, where adding a new thread has the same effect as adding a thread from my originating class.
How can i do this with executor service?
I'm currently initialising as follows:
ExecutorService executorService = Executors.newFixedThreadPool(100);
Add thread function:
final SimulatedAnnealingCallable simulatedAnnealingCallable =
new SimulatedAnnealingCallable(this, schedule);
final Future<Schedule> future = executorService.submit(simulatedAnnealingCallable);
try {
future.get();
} catch (ExecutionException ex) {
ex.getCause().printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Shutdown occurs later
The reason is that you are blocking your main thread in the future.get().
what actually happens is that your main thread starts a new future task with the executor and than you block the main thread by telling it to wait for the results of the executing task.
one way to handle this is not waiting for the future to complete and instead add functionality to let you know the task has completed using callable.
for example
public interface CompletedTask {
void completed(boolean succes);
}
// change SimulatedAnnealingCallable to receive CompletedTask in constructor
// and call the instanc's completed method
public LogicClass implements CompletedTask {
private void someFunc() {
final SimulatedAnnealingCallable simulatedAnnealingCallable =
new SimulatedAnnealingCallable(this, schedule);
executorService.submit(simulatedAnnealingCallable);
}
public void completed(boolean succes) {
System.out.println("task is completed with " + success);
}
}
HTH,
Gal
In this code
public class NoncancelableTask {
public Task getNextTask(BlockingQueue<Task> queue) {
boolean interrupted = false;
try {
while (true) {
try {
return queue.take();
} catch (InterruptedException e) {
interrupted = true;
// fall through and retry
}
}
} finally {
if (interrupted)
Thread.currentThread().interrupt();
}
}
interface Task {
}
}
What if queue is already empty? Code will swallow first exception, then retry - and wait forever?
I thought main idea of interruption is cancellation of task if it stuck on some blocking method like Thread.sleep, BlockingQueue.take(), etc.
There is similar question What is the point of restoring the interrupted status in JCIP listing 7.7? , but I don't have enough reputation to post a comment
The point of interruption is not cancellation, the two should be separate when you are thinking about interruption logic. Interruption can be used for cancellation, but as in the sample above, it can also be ignored as well.
It could be that the task returned by getNextTask(...) is so important that the thread cannot afford to exit when interrupted. Therefore, the thread will remain blocked until a task is available in the queue, unless the program completely dies or encounters a catastrophic error.
Again, this is not waiting indefinitely, only until there is a task available. What makes this sample important is that it contains a boolean check when returning, which will pass the interruption to the calling thread. That way, when the thread finally unblocks, an interruption can be checked for it to exit if necessary.
queue.take() will wait until there is something to take. Nothing is throwing an InterruptedExcpetion so the catch block won't execute. You will remain in the try block until something is added to the que or you throw an interupted exception.
Thread.currentThread().interrupt(), unless I am wrong, will not do much, because your code is single threaded right now, and that single thread is already out of the try block if it is in the finally block.
Here is an example of how to use interrupt:
public class StoppingThreads implements Runnable
{
public static void main(String[] args)
{
Thread t0 = new Thread(new StoppingThreads());
t0.start();
Thread t1= new Thread(new StoppingThreads());
t1.start();
Thread t2 = new Thread(new StoppingThreads());
t2.start();
Thread t3 = new Thread(new StoppingThreads());
t3.start();
Thread t4 = new Thread(new StoppingThreads());
t4.start();
System.out.println("All threads started");
t0.interrupt();
t1.interrupt();
}
#Override
public void run()
{
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
}
System.out.println(Thread.currentThread().getName() + " Finished");
}
}
I am making some dummy programs to learn about this java class.
My timed task calls a task which does nothing giving it 3 secs time before interrupting it.
Here's the code:
FutureTask<Integer> task = new FutureTask<>(new
Callable<Integer>(){
#Override
public Integer call() throws Exception {
int i =0;
while(i<100000){
;
}
return 0;
}
});
executor.execute(task);
try {
task.get(3000, TimeUnit.MILLISECONDS);
System.out.println("Everything was ok");
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException ex){
boolean result = task.cancel(true); //here i cancel the thread
System.out.println("the task has timed out "+result);
}
What happens is that the catch block is executed, but my program keeps running until the thread finishes. It is like task.cancel was not accepted. Why is that?
Your task is compute-bound. It doesn't perform any IO or sleep, and that's when the JVM checks the interrupt flag (any method that throws a InterruptedException). Hence your task is uninterruptible.
It's worth reading the Interrupt tutorial. Note:
What if a thread goes a long time without invoking a method that
throws InterruptedException? Then it must periodically invoke
Thread.interrupted, which returns true if an interrupt has been
received. For example:
for (int i = 0; i < inputs.length; i++) {
heavyCrunch(inputs[i]);
if (Thread.interrupted()) {
// We've been interrupted: no more crunching.
return;
}
}
and also
The interrupt mechanism is implemented using an internal flag known as
the interrupt status. Invoking Thread.interrupt sets this flag. When a
thread checks for an interrupt by invoking the static method
Thread.interrupted, interrupt status is cleared. The non-static
isInterrupted method, which is used by one thread to query the
interrupt status of another, does not change the interrupt status
flag.
Note that quite often people will write something like:
try {
// interruptible operation
}
catch (InterruptedException e) {
// do nothing
}
which doesn't reset the interrupted flag. This results in uninterruptible code. See this JavaSpecialists newsletter for more info
In a web controller, I have a parent thread that receives requests. Some requests take a long time to process. To prevent clients from timing out, I set up the parent thread to send back a byte every 2 seconds while a child thread is doing the time-consuming part of the operation.
I want to make sure I'm accounting for all possible cases of the child thread dying, but I also don't want to put in any extraneous checks.
Here is the parent thread:
// This is my runnable class
ProcessorRunnable runnable = new ProcessorRunnable(settings, Thread.currentThread());
Thread childThread = new Thread(runnable);
childThread.start();
boolean interrupted = false;
while (!runnable.done) { // <-- Check in question
outputStream.write(' ');
outputStream.flush();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// If the runnable is done, then this was an expected interrupt
// Otherwise, remember the interruption and re-interrupt after processing is done
// Or with self so that a later expected interrupt won't clear out an earlier unexpected one
interrupted = interrupted || !runnable.done;
}
}
if (runnable.runtimeException != null) {
LOG.error("Propagating runtime exception from thread");
throw runnable.runtimeException;
}
// ... Further processing on the results provided by the child thread
And here's ProcessorRunnable:
private volatile boolean done;
private volatile Result result;
private volatile RuntimeException runtimeException;
// ...
public void run() {
done = false;
try {
result = myService.timeConsumingOperation(settings);
} catch (RuntimeException e) {
runtimeException = e;
} finally {
done = true;
parentThread.interrupt();
}
}
My question is, would adding && Thread.isAlive() check in the parent thread's main loop buy me anything?
It seems that setting done = true in the finally block should do the trick, but are there some cases where this child thread could die without notifying the parent?
The finally in the child thread will always execute before it finishes. Even if that thread is interrupted or stopped, this happens via an exception that bubbles up the call stack and triggers all finallys. So, done will always be true if the child thread is interrupted.
For background tasks like this you may want to use an ExecutorService instead of raw threads. You can submit a Runnable to an ExecutorService and just call get() on the returned future to block until it is done. If you want to print out spaces while you are waiting, you can use a loop, calling the get() version with a timeout.
This method notifes an event loop to start processing a message. However, if the event loop is already processing a message then, this method blocks until it receives a notification of completed event processing (which is triggered at the end of the event loop).
public void processEvent(EventMessage request) throws Exception {
System.out.println("processEvent");
if (processingEvent) {
synchronized (eventCompleted) {
System.out.println("processEvent: Wait for Event to completed");
eventCompleted.wait();
System.out.println("processEvent: Event completed");
}
}
myRequest = request;
processingEvent = true;
synchronized (eventReady) {
eventReady.notifyAll();
}
}
This works in client mode. If I switch to server mode and the time spent in the event loop processing the message is too quick, then the method above blocks forever waiting for the event to completed. For some reason the event complete notification is sent after the processingEvent check and before the eventCompleted.wait(). It makes no difference if I remove the output statements. I can not repeat the same problem in client mode.
Why does this only happen in server mode and what can I do to prevent this happening?
Here is the eventReady wait and eventCompleted notification:
public void run() {
try {
while (true) {
try {
synchronized (eventReady) {
eventReady.wait();
}
nx.processEvent(myRequest, myResultSet);
if (processingEvent > 0) {
notifyInterface.notifyEventComplete(myRequest);
}
} catch (InterruptedException e) {
throw e;
} catch (Exception e) {
notifyInterface.notifyException(e, myRequest);
} finally {
processingEvent--;
synchronized (eventCompleted) {
eventCompleted.notifyAll();
}
}
} // End of while loop
} catch (InterruptedException Ignore) {
} finally {
me = null;
}
Here is revised code which seems to work without the deadlock problem - which BTW happened in client mode randomely after about 300 events.
private BlockingQueue<EventMessage> queue = new SynchronousQueue<EventMessage>();
public void processEvent(EventMessage request) throws Exception {
System.out.println("processEvent");
queue.put(request);
}
public void run() {
try {
while (true) {
EventMessage request = null;
try {
request = queue.take();
processingEvent = true;
nx.processEvent(request, myResultSet);
notifyInterface.notifyEventComplete(request);
} catch (InterruptedException e) {
throw e;
} catch (Exception e) {
notifyInterface.notifyException(e, request);
} finally {
if (processingEvent) {
synchronized (eventCompleted) {
processingEvent = false;
eventCompleted.notifyAll();
}
}
}
} // End of while loop
} catch (InterruptedException Ignore) {
} finally {
me = null;
}
}
If you call notifyAll and no thread is wait()ing, the notify is lost.
The correct approach is to always change a state, inside the synchronized block, when calling notify() and always check that state, inside the synchronized block, before calling wait().
Also your use of processingEvent doesn't appear to be thread safe.
Can you provide the code which waits on eventReady and notifies eventCompleted?
Your program can happen to work if your speed up or slow down your application just right e.g. if you use -client, but if you use a different machine, JVM or JVM options it can fail.
There are a number of race conditions in your code. Even declaring processingEvent volatile or using an AtomicBoolean won't help. I would recommend using a SynchronousQueue which will block the event until the processer is ready for it. Something like:
private final BlockingQueue<Request> queue = new SynchronousQueue<Request>();
...
// this will block until the processor dequeues it
queue.put(request);
Then the event processor does:
while (!done) {
// this will block until an event is put-ed to the queue
Request request = queue.take();
process the event ...
}
Only one request will be processed at once and all of the synchronization, etc. will be handled by the SynchronousQueue.
If processingEvent isn't declared volatile or accessed from within a synchronized block then updates made by one thread may not become visible to other threads immediately. It's not clear from your code whether this is the case, though.
The "server" VM is optimised for speed (at the expense of startup time and memory usage) which could be the reason why you didn't encounter this problem when using the "client" VM.
There is a race condition in your code that may be exasperated by using the server VM, and if processingEvent is not volatile then perhaps certain optimizations made by the server VM or its environment are further influencing the problem.
The problem with your code (assuming this method is accessed by multiple threads concurrently) is that between your check of processingEvent and eventCompleted.wait(), another thread can already notify and (I assume) set processingEvent to false.
The simplest solution to your blocking problem is to not try to manage it yourself, and just let the JVM do it by using a shared lock (if you only want to process one event at a time). So you could just synchronize the entire method, for instance, and not worry about it.
A second simple solution is to use a SynchronousQueue (this is the type of situation it is designed for) for your event passing; or if you have more executing threads and want more than 1 element in the queue at a time then you can use an ArrayBlockingQueue instead. Eg:
private SynchronousQueue<EventMessage> queue = new SynchronousQueue<EventMessage>();
public void addEvent(EventMessage request) throws Exception
{
System.out.println("Adding event");
queue.put(request);
}
public void processNextEvent()
{
EventMessage request = queue.take();
processMyEvent(request);
}
// Your queue executing thread
public void run()
{
while(!terminated)
{
processNextEvent();
}
}