For an embarrassing amount of time, I didn't even realize Java interrupt() could only interrupt blocking operations. I guess I thought they were like hardware interrupts, capable of just showing up anywhere without the program's cooperation.
The discussions of Thread.stop() inside of the Java group during the run up to release were some of the most interesting ones to me as a systems guy (rather than as a language person, which was a more common specialization in the group). I got a much better appreciation for the halting problem from them. And while initially the view that "most of the time it will do what you expect" carried the day, that decision was reversed on appeal :-)
I’m not sure what you mean by “reversed on appeal” as the stop() methods did make it into the platform. But there’s also Thread.destroy() whose API was defined but which I think was never actually implemented. (Fortunately.)
Edit: FWIW, I looked through the history, and it looks like Thread.destroy() was added by Bill Joy in Aug 1995. The initial implementation was "throw new NoSuchMethodError();".
Are the Google employees who write Android’s standard lib not allowed talk to the Google employees who write Google’s Android apps, or something? My experience of Android is very limited, and I mostly do server-side Java stuff, but a number of times I’ve had a look at bugs on our Android stuff and it turns out to be some ridiculous Android standard lib design flaw/bug, usually fixed in later versions which few real-life Android users have (personal favourite; the bundled HTTP client didn’t work with a server with HTTP compression enabled for most “ok, but no content” responses (204 etc) until Android 4.2 or something).
The people who write Google’s apps _have_ to be running into this stuff. But apparently either they’re not telling the standard lib people in a timely fashion, or they are but are being ignored.
Well for the interrupted() case the typical Android app never gets a close signal, it's just kill -9'd. So it's very plausible that simple no Google app ever noticed because thread.interrupt() is pretty unusual, and if nobody uses it nobody finds the edge cases.
The Android standard lib these days is OpenJDK-based, but bugs still happen there, too. Even the best of standard libs still have bugs.
Basically, when Android's libc was written they wrote `memset` wrong, such that it ignores the input parameter and always writes zeros. Nobody caught it for a while because, well, who calls `memset` with a non-zero value?
There was HN thread about it (8 years ago apparently, I feel old...):
For example, the result of "ab".split("") differs by android version. OpenJDK returns ["a", "b"], but older versions return ["", "a", "b"] and some even return ["", "a", "b", ""]. All this is strictly specified in the documentation and Java language specs, but no one ever bothered to fix it.
Generally agreed, but one should beware that even killing a process can still be quite destabilizing if that process was messing about with, say, shared memory.
Still, at least those "dangerous situations" are a bit more obvious/explicit when we're talking about processes rather than threads where everything is shared by default.
It's strange to deprecate something when you still can get exactly the same behavior by grabbing the thread's PID and then shelling out with a `kill -9`.
It's strange to deprecate something when you can still achieve the same effect in some roundabout way?
Isn't that true for ALL APIs? You could always rewrite any deprecated API yourself, using sun.unsafe or JNI if it was needed, or even compile your own patched SDK fork.
The main intend behind deprecation is telling people "we don't want to support this anymore and you shouldn't be using it".
This is totally orthogonal to "you won't be able to replicate this behavior".
There are narrow and unsafe uses of the no-arg Thread.stop() overload so it remains in the platform, although deprecated. There is an overload Thread.stop(Throwable) that is deprecated “for removal”. It’s been a no-op for several releases and the API will eventually be removed entirely.
On a Java Card or other JVM-unikernel device, Thread.stop() would be the only way for a system watchdog process (e.g. an OOM killer) to be implemented.
Java 9 has introduced an API to get the process ID but before that, there was no defined way to get it, though it is accessible in a roundabout way via the JMX API, but even then it is not guaranteed. JNI would be another alternative.
I actually like the way it is (or can be) done in Haskell: since polling an “interrupted” status would be a side effect, instead they turn the problem on its head: you can throw an async exception to the task you want to interrupt, given its ID, and it behaves essentially as if the code it was just executing has thrown a synchronous exception.
Sounds spooky, and it does require writing code in an exception-safe way, but that’s generally easy: pure code is largely exception-safe by nature, and impure code can use “bracket” (“finally”, “mask”, “ResourceT”, &c.) to acquire & release resources—and should already be using these functions anyway to handle regular synchronous exceptions. Async exceptions are very useful for killing a task that’s using too much time/memory, or initiating a graceful shutdown.
I've use Go's context based cancellation, and while I like the paradigm, it's kind of verbose. There are some that say that since it has to be passed everywhere, and can store values, it's equal to Goroutine-local storage. I'm would be surprised if they don't include a formalization in the language itself in version 2.
Making InterruptedException a checked exception was a _mind-boggling_ stupid design mistake that should have been immediately corrected but unfortunately never was. I always wince when writing scalable, long-running concurrent Java code. You need to interrupt and handle interrupts when tasks are hung, but you then need either litter up all your Java interfaces or do lots of exception detection juggling.
Forcing the programmer to add handlers for exceptions he may not even want to handle (sometimes it's okay to pass it up the call stack) just creates a mess in the source code. It's fine as a suppressible compiler warning, but not as a compiler error.
As another surprising thing, calling interrupted() actually clears the interrupted bit. If it's true, you pretty much have to throw InterruptedException. Otherwise, you have to re set the bit, and exit quietly.
> calling isInterrupted() actually clears the interrupted bit.
Thats incorrect. Calling Thread#interrupted[0] clears the interrupt status and returns true if the current thread was interrupted. Thread#isInterrupted()[1] only returns the value of the interrupt status on the thread receiving the method call. The interrupt status is unaffected by that method call.