I have a servlet, and it is a singleton.
In the init, I create the producer and the consumers.
consumer = new MyThread();
consumer.start();
and the method run is like this:
#Override
public void run() {
while (!isShutdown()) {
if (queue.isEmpty())
queue.wait();
else
...
}
}
then i have the destroy method.
that set shutdown to true and I use .join
consumer.setShutdown(true);
consumer.join();
but the method .join got lock.. and never finishes.
If I change the queue.wait to Thread.sleep(), it works... but I don't want to change... what I'm doing wrong?
if I don't finish the thread, I got it:
SEVERE: The web application [/test] appears to have started a thread named [Comsumer0] but has failed to stop it. This is very likely to create a memory leak.
Using wait/notify methods is the old way to create a Consumer-Producer pattern.
It is better to use BlockingQueue.
BlockingQueue.put() - for Producer, and BlockingQueue.poll() - for Consumer.
BlockingQueue hides wait method underneath BlockingQueue.poll, BlockingQueue.put and will block a Consumer thread until Producer adds value to queue.
To fix the example above, you should make it wait for a finite amount of time like queue.wait(1000), or wake consumer thread explicitly calling queue.notify().
Most likely the queue is empty and since you have shutdown you never send anything into the queue to cause it to wake up.
Fix this either by sending a dummy message to the queue after setting the shutdown flag or by just removing the shutdown flag completely and sending a shutdown command to the queue.
Also be aware that if your shutdown flag is not volatile (or AtomicBoolean) then one thread may not see it being set by the other due to caching inside the CPU.
This is what the BlockingQueue is for:
BlockingQueue queue = new ArrayBlockingQueue(5);
// ...
while (!isShutdown()) {
Object poll = queue.poll(5, TimeUnit.SECONDS);
}
you should change the design as advised above, or if you don't want to change your code, change your setShutdown() method body and statement to notify the queue.
public void setShutdown(boolean shutdown) {
this.shutdown = shutdown;
this.queue.notifyAll();
}
Related
We have a callable class A which actually makes HttpCalls through HttpClient.executeMethod(GetMethod) with a lot of other pre-computations. HttpClient is initialized in the constructor with MultiThreadedHttpConnectionManager.
Another class B creates list of threads for class A through ExecutorService and submits task to the pool and expects future objects to be returned. We have following logic in class B:
for( Future f : futures ){
try{
String str = f.get(timeOut, TimeUnit.SECONDS);
}catch(TimeoutException te){
f.cancel(true);
}
}
This way, our thread gets terminated after a specified time and execution of the task will be terminated and this thread will be available for next task.
I want to confirm the following:
If an external connection is made though HttpClient, how does that get handled on future.cancel of the thread?
In above case or in general, does the http connection pool gets the connection back by properly releasing the previous one? We do release the connection in finally but I don't think interrupting the thread will hit that block.
Could it cause any kind of leak on client or extra resource consumption on the server?
Thanks!
It depends.
If the Http Client uses java.net.Socket, its I/O isn't interrruptible, so the cancel will have no effect.
If it uses NIO, the interrupt will close the channel and cause an exception. At the server this will cause a premature end of stream or an exception on write, either of which the server should cope with corectly.
I have a few executor services which schedule local tasks such as reading a file, connecting to db etc. These processes do huge amount of logging, which is extensive based on the fact there are many threads running concurrently, writing their own thing into the log.
Now, at some point in time an exception can be raised, which reaches the main method where all exceptions are caught. I am then shutting down all the services and cancelling each task, hoping to prevent all further messages to the log. Unfortunately, the messages are still showing up after I shut everything down... Any ideas?
UPDATE:
Here is some code
public class Scheduler{
private final ExecutorService service;
private final ConcurrentMap<Object, Future<V>> cache;
...
public void shutDown() {
service.shutdownNow();
for (Future task : cache.values())
task.cancel(true);
}
The task will carry on running until it reaches a point where it detects the Thread has been interrupted. This can happen when calling some System or Thread functions and you may get an exception thrown. In your case you probably need to check yourself by calling
Thread.currentThread().isInterrupted()
It is a good idea to do this if your code runs loops and you are expecting to be stopped in this way.
When you shutdownNow your executor or call cancel(true) (by the way shutdownNow already cancels the already submitted tasks so your loop is unnecessary) your tasks get interrupted.
Depending on how they react to the interruption, they might then:
stop what they are doing immediately
stop what they are doing after a while, because the interruption signal is not being checked regularly enough
continue doing what they are doing because the interruption signal has been ignored
For example, if your tasks run a while(true) loop, you can replace it with something like:
while(!Thread.currentThread().isInterrupted()) {
//your code here
}
cleanup();
//and exit
Another example:
for (int i = 0; i < aBigNumber; i++) {
if (Thread.currentThread().isInterrupted()) { break; }
//rest of the code for the loop
}
cleanup();
//and exit
Another example, if you call a method that throws InterruptedException:
try {
Thread.sleep(forever); //or some blocking IO or file reading...
} catch (InterruptedException e) {
cleanup();
Thread.currentThread.interrupt();
//and exit
}
Executors support 2 approaches of shutdown
shutdown() : Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
shutdownNow() : Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks.
Ref : http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()
- Try using the shutdowNow() method, it will shutdown all the task started by this Executor throwing InterruptedException, but IO and Synchronized operation can't be interrupted.
Eg:
ExecutorService executor = Executors.newFixedThreadPool();
executor.execute();
...
...
executor.shutdownNow();
- cancel(true) method can be used with submit() method to shutdown a particular task.
I have written some code that submits a callable to an executor, storing the future in a map against an id. In the call method I wait for a flag to be set before proceeding. Basically I need to wait for an external operation to return to me and say we are done - here is the data and now you can continue... I dont think what I have is correct:
public class MyClass implements Callable<Boolean> {
---
---
private boolean done = false;
#override
public Boolean call() {
-- wait for flag to be set...
//continue....
}
}
--main code--
//create the above class..
//submit it...
//get the future store in map...
//-- wait for response from external application...
///tie it up with an id
//set the attribute so the callable can continue and complete..
Questions:
The above will not work as I am returned a Future and not the object. I was thinking of maybe creating a new interface which inherits from the callable class - does that make sense?
I need the thread to wait and then die if no response is received. Is it possible to set that on a thread at all?
You can schedule a task which will cancel the waiting task. When the waiting task finishes it can cancel the scheduled task. (which ever finished first will cancel the other)
This assumes you have a task which is interruptible in the first place.
there is a wait(long timeout) function available.. heres some documentation on it
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html
with this wait(long timeout) function, the thread will wait until it gets a notify() (or notifyAll()) OR until the timout expires.
any of the following will break the wait();
notify();
notifyAll();
timout gets reached
Use the Future#get(long, TimeUnit).
This will wait for some time for an answer, and throw a TimeoutException if there is no return value in the given period. Then just catch the exception and let the thread finish grafefully.
We have a standalone java application doing some background processing on a Debian machine. The jobs it has to handle are send through RabbitMQ messages.
When the java application needs to be upgraded we need to stop it (kill it). But we have to be sure that no consumers are currently processing a message. What is, in your experience, the best way to achieve this?
We tried to send a 'SHUTDOWN' message to a consumer, but we can't seem to close the queue or channel?! It freezes the application!
Or is there another solution where we could for example auto shutdown the application, without doing the kill command in linux?
Thx to share you experience.
Greetings
The RabbitMQ Java libraries do not provide (AFAIK) anything which would automatically postpone the shutdown of a consumer process while some messages are still being processed. Therefore you'll have to do this yourself.
If your application can tolerate it, just shut down. Any message which had not been acknowledged at that point will remain on the queue within the broker and will be re-delivered when the consumer comes back up.
If you can't tolerate that and you absolutely must ensure that all in-progress message processing finishes, then you need to follow advice similar to what's found in this answer and do the following in your shutdown handler:
Set an "all threads should exit" flag to true
Join with each of the threads in your thread pool
Exit gracefully
That implies that each of your message processing threads (assuming you have multiple threads processing messages concurrently) need to follow this general pattern:
Pull a message from the queue and process it
Ack the message which was just processed
If the "all threads should exit" flag is true, exit the thread function
Rinse, repeat
Hope that helps.
Here's my take on it.
I created my subclass of DefaultConsumer (BasicConsumer) which provides isCancelled() and implements handleCancelOk() which sets a "cancelled flag" to true.
Start sequence:
consumers = new ArrayList<BasicConsumer>();
consumers.add(...)
Stop sequence:
// Cancel all consumers
for (BasicConsumer consumer : consumers) {
try {
consumer.getChannel().basicCancel(consumer.getConsumerTag());
} catch (Exception e) {
// report
}
}
// Wait for all consumers to be cancelled
Timeout timeout = ...;
while (!consumers.isEmpty() && !timeout.isElapsed()) {
// Remove cancelled consumers
for (Iterator<BasicConsumer> iterator = consumers.iterator(); iterator.hasNext();) {
if (iterator.next().isCancelled())
iterator.remove();
}
}
// Here we could force-close the remaining timed-out consumers if we
// used our own ExecutorService by shutting down all of its threads.
connection.close();
Relevant RabbitMQ ML thread: How to shutdown cleanly a Java application using Consumers?
I have a basic question. Why and how SelectableChannel's register method can be in blocking call.
Let me provide a scenario.
I have created a Selector object in class Register as follows.
private static Selector selector = Selector.open();
I also have a method in same class(Register) to register the channel with the selector.
public static SelectionKey registerChannel(SelectableChannel channel, int ops)
throws IOException {
channel.configureBlocking(false);
return channel.register(selector, ops);
}
And there is another class named Request, which has method which reads the data from channels, processes and calls following method to register the channel.
selectonKey = Register.register(socketChannel, SelectionKey.OP_READ);
Here at this point the thread is blocked, not giving clue of what it is waiting for.
I have verified that the selector is open. Please provide me some help to understand how can I resolve this. Is there any lock that I can release.
Any input would be appreciated.
Adding to what I described. Further tests revealed that if the Register.register method is called from the same thread, it is able to register but after that if some other thread tries to invoke the method, thread doesn,t move ahead.
This is a basic feature of most NIO implementations that isn't obvious from the documentation.
You need to make all register calls from the same thread that is doing your selecting or deadlocks will occur. Usually this is done by providing a queue of registrations/deregistrations/interest-changes that is written to and then selector.wakeup() is called. When the selecting thread wakes up it checks the queue and performs any requested operations.
You need to use a lock and manually synchronize.
In the same thread you are running the selector loop have a ReentrantLock:
final ReentrantLock selectorLock = new ReentrantLock();
Then when you need to register with the selector do something like this:
selectorLock.lock();
try {
selector.wakeup();
socketChannel.register(selector, ops);
} finally {
selectorLock.unlock();
}
Finally, during your loop that you are calling accept(), something like this:
selectorLock.lock();
selectorLock.unlock();
selector.select(500);
And then continue on with the rest of your logic.
This construct guarantees that the register() call will not block by ensuring that there is never another select() between corresponding wakeup() and register() calls.
I agree with #Darron's answer that you should pass register calls to the selector thread, but you should not use selector.wakeup as it would introduce race conditions (imagine selector thread was busying processing other registrations and your wakeup fail to wake up anyone). Luckily, Java NIO provided Pipe so that you can let the selector listen for both register calls and other events.
Basically, here's what needs to be done:
val registrationPipe = Pipe.open()
registrationPipe.source().configureBlocking(false)
registrationPipe.source().register(selector, SelectionKey.OP_READ)
// now start your selector thread
// now to register a call from other threads using message pleaseRegisterMe
registrationPipe.sink().write(pleaseRegisterMe)
// inside your selector thread
val selectionKey = iterator.next()
if (selectionKey.channel() === registrationPipe.source()) {
registrationPipe.source().read(pleaseRegisterMe)
// do something with the message pleaseRegisterMe and do the actual register
}
Here is a full working example.
Have you tried printing a stack trace of all threads in your program (using either kill -QUIT in Unix or Ctrl+Break in Windows or using the jstack utility)?
AbstractSelectableChannel contains a lock on which configureBlocking and register need to synchronize. This lock also is accessible through the blockingLock() method, and so another thread could potentially be holding the lock causing your register call to block indefinitely (but without a stack trace it's difficult to tell).
Register your channel from any thread:
synchronized (selectorLock2) {
selector.wakeup();
synchronized (selectorLock1) {
channel.register(selector, ops);
}
}
Your selector loop should look like this:
while (true) {
synchronized (selectorLock1) {
selector.select();
}
synchronized (selectorLock2) {}
....
}