...
This noncompliant code example shows a thread that fills a vector with strings. The thread is shut down stopped after a fixed period amount of time time.
Code Block | ||
---|---|---|
| ||
public class Container implements Runnable { private final Vector<String> vector = new Vector<String>(); public Vector<String> getVector() { return vector; } public void run() { String string = null; BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); do { System.out.println("Enter another string"); try { string = in.readLine(); } catch (IOException e) { // Forward to handler } vector.add(string); } while (!"END".equals(string)); } public static void main(String[] args) throws InterruptedException { ContainerThread cthread = new Container(); Thread thread = Thread(new ThreadContainer(c)); thread.start(); Thread.sleep(5000); thread.stop(); } } |
Since vector
Because the class Vector
is thread-safe, it is only accessible to this program while operations performed by multiple threads on its shared instance are expected to leave it in a consistent state. That isFor instance, the Vector.size()
method always reflects the true number of elements in the vector . When a new even when an element is added to the vector, it adjusts its internal data and its internal data is temporarily inconsistent. But the vector or removed. This is because the vector instance uses its own intrinsic lock to prevent other threads from accessing it while its state is temporarily inconsistent.
Wiki Markup |
---|
However, the {{Thread.stop()}} method causes the thread to stop what it is doing and throw a {{ThreadDeath}} objectexception, and also to release all locks that it has acquired \[[API 06|AA. Java References#API 06]\]. If the thread is currently in the process of adding a new string to the vector when it getsis stopped, then the vector may become visibleaccessible while init is in an inconsistent state. This might mean, for For instance, that {{Vector.size()}} may isbe 3three while the vector actually only contains 2two elements. |
Compliant Solution (volatile
flag)
This compliant example solution stops the thread by making use of using a volatile
flag. An accessor method shutdown()
is used to set the flag to true
, after which the thread can start the cancellation process.
Code Block | ||
---|---|---|
| ||
public class Container implements Runnable { private final Vector<String> vector = new Vector<String>(); private volatile boolean done = false; public Vector<String> getVector() { return vector; } public void shutdown() { done = true; } public void run() { String string = null; BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); do { System.out.println("Enter another string"); try { string = in.readLine(); } catch (IOException e) { // Forward to handler } vector.add(string); } while (!done && !"END".equals(string)); } public static void main(String[] args) throws InterruptedException { ContainerThread cthread = new Container(); Thread thread = Thread(new ThreadContainer(c)); thread.start(); Thread.sleep(5000); c.shutdown(); return; } } |
Compliant Solution (Interruptible)
This compliant example solution stops the thread by making use of a volatile
flag. An accessor method shutdown()
is used to set the flag to true
, after which the thread can start the cancellation processusing the Thread.interrupted()
method.
Code Block | ||
---|---|---|
| ||
public class Container implements Runnable { private final Vector<String> vector = new Vector<String>(); public Vector<String> getVector() { return vector; } public void run() { String string = null; BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); do { System.out.println("Enter another string"); try { string = in.readLine(); } catch (IOException e) { // Forward to handler } vector.add(string); } while (!Thread.interrupted() && !"END".equals(string)); } public static void main(String[] args) throws InterruptedException { Container c = new Container(); Thread thread = new Thread(c); thread.start(); Thread.sleep(5000); thread.interrupt(); Thread.sleep(5000); thread.interrupt(); } } } } |
This method interrupts the current thread, however, it does not stop the thread unless the logic polls the interrupted flag using the method Thread.interrupted()
to stop performing any pending actions.
Compliant Solution (RuntimePermission stopThread
)
...
Code Block | ||
---|---|---|
| ||
class StopSocket extends Thread { private Socket s; private volatile boolean done = false; public void run() { while(!done) { try { s = new Socket("somehost", 25); BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); String s = null; while((s = br.readLine()) != null) { // Blocks until end of stream (null) } } catch (IOException ie) { // Forward to handler } finally { done = true; } } } public void shutdown() throws IOException { done = true; } } class Controller { public static void main(String[] args) throws InterruptedException, IOException { Thread StopSocket ssthread = new StopSocket(); Thread t = Thread(new ThreadContainer(ss)); t.start(); Thread.sleep(1000); ss.shutdown(); } } |
A Socket
connection is not affected by the InterruptedException
that results with the use of the Thread.interrupt()
method. The boolean
flag solution does not work in such cases.
...