From: Alan Gutierrez on
markspace wrote:
> Alan Gutierrez wrote:
>
>> With a terminal value to shutdown the queue, and with the thread
>> unexposed to the client, there seems to be no way to send an interrupt
>> to the thread, so it becomes the classic unreachable checked exception
>> block.
>
>
> See, I'd go the other way. Even though I don't personally know any way
> your thread is exposed to a client either, I'd still let an interrupt
> kill the thread. Two reasons for this:
>
> 1) There may be some way a client can send a SIGHUP or similar through
> the console, which the JVM might propagate to all threads, for an
> orderly shutdown (kill -9 is disorderly and abrupt).

There is such a way to accept a SIGTERM, Runtime.addShutdownHook, but it
is my understanding that it is up to the developer to implement the
orderly shutdown of her own threads. There is no mention of threads
being shutdown with interrupt.

In the case of my library, you would call a publicly exposed shutdown
method that would terminate the worker thread in a fashion that
indicated an orderly shutdown.

So there are no interrupts sent by the virtual machine at shutdown.
Interrupting a thread is something done deliberately.

I got to musing about daemon threads, too. I began to wonder if the JVM
simply stopped executing statements, or if the overly ambitions stop,
start, ThreadDeath mechanism still played some part in shutdown.

This program below shows that no interrupt it sent to the main thread
and nothing propagates out of the daemon thread, on OSX Sun JVM and on
Linux running Open JDK. Compile and run and send a SIGTERM using Ctl+C
or kill and the program stops dead.

public class SetDaemon {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
public void run() {
try {
for (;;) {}
} catch (Throwable e) {
e.printStackTrace();
if (e instanceof Error) {
throw (Error) e;
}
throw (RuntimeException) e;
}
}
});
thread.setDaemon(true);
thread.start();
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


> 2) Another programmer might assume that any thread can be killed with an
> interrupt, and might be confused or frustrated when it can't. In this
> light, it's just a bit of future proofing and courtesy to make your
> thread work in the standard way.

Point taken. I'll throw an exception instead. I maintain that this tread
is part of the internal state of the library and sending it an interrupt
is a programming error, but as a programming error, it should throw an
exception the moment the error is detected.

--
Alan Gutierrez - alan(a)blogometer.com - http://twitter.com/bigeasy
From: Alan Gutierrez on
ClassCastException wrote:
> On Tue, 20 Jul 2010 21:19:58 -0500, Alan Gutierrez wrote:
>
>> With a terminal value to shutdown the queue, and with the thread
>> unexposed to the client, there seems to be no way to send an interrupt
>> to the thread, so it becomes the classic unreachable checked exception
>> block. How do you handle the interrupt that never happens? I decided
>> that trying again after the impossible was as good as giving into the
>> impossible.
>
> My usual way of handling an "unreachable" checked exception block is
> "throw new Error();".

Thank you. I'll throw runtime exceptions when I catch an
InterruptedException I was not expecting, instead of retrying. I said as
much in my last response.

--
Alan Gutierrez - alan(a)blogometer.com - http://twitter.com/bigeasy
From: Alan Gutierrez on
markspace wrote:
> Lew wrote:
>
>> You're mistaken. The assignment in 'methodA()' of 'data'
>> /happens-before/ the write to 'set', which latter is synchronized.
>> The read in 'methodB()' of 'data' /happens-after/ the read of 'set',
>> which latter is synchronized on the same monitor. Therefore the read
>> is guaranteed to see the write.
>
> Brian Goetz calls this piggy-backing in JCIP. (He uses a volatile
> variable as an example, which is why I was confused about synchronized
> blocks.) And he says it's a dangerous thing to do because it's hard to
> reason out these side effect correctly, and hard for maintenance
> programmers to spot them as well. So to the OP and others, don't rely
> on these side effects. Put all data in a synchronized block and you'll
> be less likely to wonder what the heck is going on six months after your
> wrote the code.

The OP is perfectly capable of reasoning out the usage of a BlockingQueue.

--
Alan Gutierrez - alan(a)blogometer.com - http://twitter.com/bigeasy
From: markspace on
Alan Gutierrez wrote:

> Point taken. I'll throw an exception instead. I maintain that this tread
> is part of the internal state of the library and sending it an interrupt
> is a programming error, but as a programming error, it should throw an
> exception the moment the error is detected.


A good idea, I think. If you consider an interrupt to be an error, then
you certainly want to make note of any interrupts that you find.

Other ideas: log the error, but continue running anyway. This might be
problematic since you are the logging thread in this case. Consider
(also?) writing to stderr.

Another one: I've seen code that attempted an orderly shutdown on
SIGHUP, but if it caught a second one, then someone is really trying to
stop your process (probably a frustrated operator at the console mashing
the control-C button). On the first interrupt, continue running
(probably record the interrupt though) while attempting an orderly
shutdown. On the second interrupt, die immediately.

Just tossin' ideas out....

From: Lew on
Alan Gutierrez wrote:
>>> With a terminal value to shutdown the queue, and with the thread
>>> unexposed to the client, there seems to be no way to send an interrupt
>>> to the thread, so it becomes the classic unreachable checked exception
>>> block.
>

'InterruptedException' is not about SIGINT or other OS signals, but
about the Java method 'Thread#interrupt()'.
<http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/
lang/Thread.html#interrupt()>
<http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/
lang/InterruptedException.html>

There is excellent advice in /Java Concurrency in Practice/ (JCIP.
Part of the reason to catch it is that the JVM apparently can throw
spurious 'InterruptedException's.

Read JCIP (by Brian Goetz et al.).

Alan Gutierrez wrote:
> There is such a way to accept a SIGTERM, Runtime.addShutdownHook, but it
> is my understanding that it is up to the developer to implement the
> orderly shutdown of her own threads. There is no mention of threads
> being shutdown with interrupt.
>
> In the case of my library, you would call a publicly exposed shutdown
> method that would terminate the worker thread in a fashion that
> indicated an orderly shutdown.
>
> So there are no interrupts sent by the virtual machine at shutdown.
> Interrupting a thread is something done deliberately.
>

Or not, if you get a spurious interruption.

> I got to musing about daemon threads, too. I began to wonder if the JVM
> simply stopped executing statements, or if the overly ambitions stop,
> start, ThreadDeath mechanism still played some part in shutdown.
>
> This program below shows that no interrupt it sent to the main thread
> and  nothing propagates out of the daemon thread, on OSX Sun JVM and on
> Linux running Open JDK. Compile and run and send a SIGTERM using Ctl+C
>

Ctrl-C sends SIGINT, not that that is relevant to
'InterruptedException'.

> or kill and the program stops dead.
>
> public class SetDaemon {
>      public static void main(String[] args) {
>          Thread thread = new Thread(new Runnable() {
>              public void run() {
>                  try {
>                      for (;;) {}
>                  } catch (Throwable e) {
>                      e.printStackTrace();
>                      if (e instanceof Error) {
>                          throw (Error) e;
>                      }
>                      throw (RuntimeException) e;
>                  }
>              }
>          });
>          thread.setDaemon(true);
>          thread.start();
>          try {
>              Thread.sleep(Long.MAX_VALUE);
>          } catch (InterruptedException e) {
>              e.printStackTrace();
>          }
>      }
>
> }

markspace wrote:
>> 2) Another programmer might assume that any thread can be killed with an
>> interrupt, and might be confused or frustrated when it can't.  In this
>> light, it's just a bit of future proofing and courtesy to make your
>> thread work in the standard way.
>

Alan Gutierrez wrote:
> Point taken. I'll throw an exception instead. I maintain that this tread
> is part of the internal state of the library and sending it an interrupt
> is a programming error,
>

Or a spurious 'InterruptedException'.

> but as a programming error, it should throw an
> exception the moment the error is detected.
>

Unless it was a spurious exception.

--
Lew