The
Blocking state is the most interesting of the four States mentioned above and deserves further discussion. Thread blockage can be caused by the following five reasons:
(1) Call sleep (the number of milliseconds) to make the thread into a "sleeping" state. This thread is not going to run within the specified time. The
(2) pauses the execution of the thread with suspend (). The run state is not returned unless the thread receives the resume () message. The
(3) pauses the execution of the thread with Wait (). Unless the thread receives a nofify () or notifyall () message, it will not become "operational" (Yes, it looks very similar to reason 2, but there is one obvious difference that we are going to reveal soon). The
(4) thread is waiting for some IO (input/output) operation to complete. The
(5) thread attempted to invoke the "sync" method of another object, but that object was locked for temporary use. The
can also call yield () (a method of the thread class) to automatically discard the CPU so that other threads can run. However, the same thing happens if the scheduling mechanism feels that our threads have had enough time to jump to another thread. That is, nothing can prevent the scheduling mechanism from restarting our threads. After the thread has been blocked, there are some reasons why it cannot continue to run.
The following example shows all five ways to get into a blocking state. They all exist in a file called Blocking.java, but here are scattered fragments to explain (you can notice the "continued" and "continuing" signs before and after the fragment.) Use the tools described in chapter 17th to link these fragments together. First let's look at the basic framework:
 
: Blocking.java//demonstrates the various ways a thread//can be blocked.
Import java.awt.*;
Import java.awt.event.*;
Import java.applet.*;
Import java.io.*;
The basic framework///////////class Blockable extends Thread {private Peeker peeker;
protected TextField state = new TextField (40);
protected int i;
Public blockable (Container c) {c.add (state);
Peeker = new Peeker (this, c);
public synchronized int read () {return i;}
protected synchronized void Update () {State.settext (GetClass (). GetName () + "state:i =" + i); public void Stoppeeker () {//Peeker.stop (); Deprecated in Java 1.2 peeker.terminate ();
The preferred approach} class Peeker extends Thread {private blockable B;
private int session;
Private TextField status = new TextField (40);
Private Boolean stop = false;
Public Peeker (blockable B, Container c) {c.add (status);
this.b = b;
Start (); public void Terminate () {StOP = true;
public void Run () {while (!stop) {Status.settext b.getclass (). GetName () + "Peeker" + (++session) + ";
Value = "+ B.read ());
try {sleep (100); The catch (Interruptedexception e) {}}}}///:continued
The
Blockable class is intended to be a base class for all classes in this example. A Blockable object contains a TextField (text field) named state that displays information about the object. The method used to display this information is called Update (). We find that it uses getclass.getname () to produce the class name, not just print it out, because update (0) does not know the exact name of the class that it calls, because the class is derived from the blockable.
in blockable, the change indicator is an int i; the run () method of the derived class adds value to it.
for each Bloackable object, a thread of the Peeker class is started. The Peeker task is to call the Read () method, check the Blockable object associated with yourself, see if I have changed, and then report the results with its status text field. Note that both read () and update () are synchronized and it is important that the lock of the object is free to be lifted.
1. Sleep
The first test of this program is made by Sleeping ():
///:continuing/////////////Blocking via Sleep ()///////////class Sleeper1 extends blockable {PU
Blic Sleeper1 (Container c) {super (c);}
Public synchronized void Run () {while (true) {i++;
Update ();
try {sleep (1000); Sleeper2 extends blockable {public Sleeper2 (Container c) {supe) of catch (Interruptedexception e) {}}} R (c);
public void Run () {while (true) = Change ();
try {sleep (1000);
The catch (Interruptedexception e) {}} is public synchronized void change () {i++;
Update (); }}///:continued
in Sleeper1, the entire run () method is synchronized. We can see that the peeker associated with this object works properly until we start the thread, and then the peeker stops completely. This is a form of "blockage": Because Sleeper1.run () is synchronized, and once the thread starts, it must be inside the run (), and the method never discards the object lock, causing the peeker thread to jam. The
Sleeper2 provides a solution by setting up a run that is not synchronized. Only the change () method is synchronized, so even though run () is within the sleep (), Peeker still has access to the Sync Method--read () that it needs. Here, we can see that Peeker will continue to run after the Sleeper2 thread is started.
2. Pause and Redo
The next part of this example introduces the overview of "suspend" or "pause" (Suspend). The thread class provides a method named Suspend () that temporarily aborts a thread, and a method named Resume () for resuming the execution of a thread from a pause. Obviously, we can infer that resume () is called by a thread outside of the suspend thread. In this case, you need to use a separate class called Resumer (the recovery device). Each class that demonstrates the suspend/restore process has an associated restore. As follows:
: Continuing///////////Blocking via suspend ()///////////class Suspendresume extends blockable {public suspendres
Ume (Container c) {super (c);
New Resumer (this);
} class SuspendResume1 extends Suspendresume {public SuspendResume1 (Container c) {super (c);}
Public synchronized void Run () {while (true) {i++;
Update (); Suspend (); Deprecated in Java 1.2}} class SuspendResume2 extends Suspendresume {public SuspendResume2 (Container c) {
Super (c);}
public void Run () {while (true) {a change (); Suspend ();
Deprecated in Java 1.2}} public synchronized void change () {i++;
Update ();
} class Resumer extends Thread {private Suspendresume sr;
Public Resumer (Suspendresume sr) {this.sr = SR;
Start ();
public void Run () {while (true) {try {1000); catch (Interruptedexception e) {} sr.resume (); Deprecated in Java 1.2}}}: Continued
SUSPENDRESUME1 also provides a synchronized run () method. Similarly, when we start this thread, we find that the peeker associated with it enters the "blocked" state, waiting for the object lock to be released, but that never happens. As usual, the problem was solved in SuspendResume2, which did not synchronize the entire run () method, but instead adopted a separate synchronous change () method.
For Java 1.2, it should be noted that suspend () and resume () have been strongly opposed because the suspend () contains object locks, so the "deadlock" phenomenon is very easy to appear. In other words, it's easy to see a lot of locked objects waiting foolishly for each other. This can cause the entire application to "solidify". Although they can still be seen in some old programs, you should avoid it in any case when you write your own program. This chapter will later describe what the correct scenario is.
3. Waiting and notification
Through the first two examples of practice, we know that either sleep () or suspend () does not unlock itself when it is called. When you need to use object locks, be sure to pay attention to this issue. On the other hand, the wait () method is unlocked when invoked, which means that other synchronization methods in the thread object can be invoked during the execution of Wait (). But in the next two classes, we see that the run () method is "synchronized." During wait (), Peeker still has full access to the synchronization method. This is because wait () unlocks the object when it suspends the method that is called internally.
We can also see two forms of wait (). The first form takes a parameter in milliseconds, and it has the same meaning as in sleep (): Pause the specified time. The difference is that in wait (), the object lock has been lifted, and it is free to quit waiting () because a notify () can force the time to pass.
The second form does not take any parameters, which means that wait () continues to execute until notify () is involved. And after a period of time, will not be suspended.
A special place for Wait () and notify () is that both methods are part of the underlying class object and are not part of the thread like Sleep (), suspend (), and resume (). Although the surface looks a little strange--making something that specializes in threading a part of a common base class--it's a relief to think about it, because the object locks they manipulate are also part of each object. Therefore, we can place a wait () inside any synchronization method, regardless of whether or not the thread-related processing is prepared in that class. In fact, the only place we can call wait () is inside a synchronized method or block of code. If you call Wait () or notify () in an unsynchronized method, even though the program will still compile, you will get a illegalmonitorstateexception (Illegal monitor state violation) when you run it. And there's a little bit of an inexplicable message: "Current thread not owner" (currently threads are not everyone.) Note that sleep (), suspend (), and resume () can be invoked in different steps because they do not need to operate on the lock.
You can only call Wait () and notify () for your own locks. In the same way, you can still compile code that attempts to use incorrect locking, but as usual it will produce the same illegalmonitorstateexception violation. We have no way to fool the system with other people's object locks, but we can ask another object to perform the appropriate operation on its own lock. So one way to do this is to create a synchronization method that invokes notify () for its own object. But in notifier, we see a notify () inside the synchronization method:
Synchronized (WN2) {
wn2.notify ();
}
Where Wn2 is an object of type WaitNotify2. Although not part of the WaitNotify2, this method still obtains a lock on the Wn2 object. At this time, it is legal for Wn2 to invoke notify () and will not get illegalmonitorstateexception violation.
///:continuing///////////Blocking via Wait ()///////////class WaitNotify1 extends blockable {PU
Blic WaitNotify1 (Container c) {super (c);}
Public synchronized void Run () {while (true) {i++;
Update ();
try {wait (1000);
WaitNotify2 extends blockable {public WaitNotify2 (Container c) {} catch (Interruptedexception e) {}}}
Super (c);
New Notifier (this);
Public synchronized void Run () {while (true) {i++;
Update ();
try {wait ();
The catch (Interruptedexception e) {}}} class Notifier extends Thread {private WaitNotify2 wn2;
Public Notifier (WaitNotify2 wn2) {this.wn2 = WN2;
Start ();
public void Run () {while (true) {try {2000);
The catch (Interruptedexception e) {} synchronized (WN2) {wn2.notify (); {}}}}///:continued
If you have to wait for some other condition (to be controlled from the thread) and do not want to be online agenda have been foolishly waiting, you usually need to use wait (). Wait () allows us to place the thread in the "Sleep" state while "actively" waiting for the condition to change. And only when a notify () or Notifyall () is changed, the thread wakes up and checks to see if the condition is changed. Therefore, we think it provides a means of synchronizing between threads.
4. Io blocking
If a data stream must wait for some IO activity, it will automatically enter the "blocked" state. In the sections listed below, there are two classes that work together with generic reader and writer objects (using Java 1.1 streams). In the test model, however, a piped stream of data is set up so that two threads can safely pass data between each other (which is precisely the purpose of using a pipe stream). The
sender the data into the writer and sleeps for a random length of time. However, the receiver itself does not include sleep (), suspend (), or wait () methods. However, when the read () is executed, if no data exists, it automatically enters the "blocked" state. As follows:
///:continuing class Sender extends blockable {//Send private Writer out;
Public Sender (Container C, Writer out) {super (c);
This.out = out;
public void Run () {while (true) {for (char c = ' A '; c <= ' z '; C + +) {try {i++;
Out.write (c);
State.settext ("Sender Sent:" + (char) c);
Sleep ((int) (3000 * math.random ()); The catch (Interruptedexception e) {} catch (IOException e) {}}} class Receiver extends Blockabl
e {private Reader in;
Public Receiver (Container C, Reader in) {super (c);
This.in = in; public void Run () {try {a) {i++;/show Peeker it ' s alive//Blocks until Chara
Cters are There:state.setText ("Receiver read:" + (char) in.read ());
The catch (IOException e) {e.printstacktrace ()} }}///:continued
These two classes also feed the information into their state field and modify the I value so that peeker knows that the thread is still running.
5. Test
Surprisingly, the main program slice (applet) class is very simple, which is why most jobs have been placed into the blockable framework. Roughly speaking, we created an array of blockable objects. And since each object is a thread, they take their actions when the "Start" button is pressed. There is also another button and actionperformed () clause, which is used to abort all Peeker objects. Because Java 1.2 "opposes" using the Stop () method of thread, consider using this eclectic form of abort.
to establish a connection between sender and receiver, we created a pipedwriter and a pipedreader. Note that pipedreader in must be connected with the Pipedwriterout through a builder parameter. After that, everything we put inside out can be extracted from in--it seems that those things are transmitted through a "pipe". The in and out objects are then passed to the receiver and sender builders, which treat them as any type of reader and writer (i.e., they are "traced"). The array of
Blockable handle B is not initialized at the beginning of the definition because the piped data stream is not set before the definition (the need for a try block will become an impediment):
: Continuing///////////Testing Everything///////////public class Blocking Applet {private Button St
Art = New button ("Start"), Stoppeekers = New button ("Stop peekers");
Private Boolean started = false;
Private blockable[] B;
Private PipedWriter out;
Private Pipedreader in;
public void Init () {out = new pipedwriter ();
try {in = new Pipedreader (out); catch (IOException e) {} b = new blockable[] {new Sleeper1 (this), new Sleeper2 (this), new Suspendr Esume1 (this), the new SuspendResume2 (this), the new WaitNotify1 (this), the new WaitNotify2 (this), New Sender (t
He, out), the new Receiver (this, in)};
Start.addactionlistener (New Startl ());
Add (start);
Stoppeekers.addactionlistener (New Stoppeekersl ());
Add (stoppeekers);
Class Startl implements ActionListener {public void actionperformed (ActionEvent e) {if (!started) {
started = true; for (int i = 0; i < b.length;
i++) B[i].start (); Class STOPPEEKERSL implements ActionListener {public void actionperformed (ActionEvent e) {//Dem Onstration of the preferred//alternative to Thread.stop (): for (int i = 0; i < b.length; i++) b[i
].stoppeeker ();
} public static void Main (string[] args) {Blocking applet = new Blocking ();
Frame aframe = new Frame ("Blocking"); Aframe.addwindowlistener (New Windowadapter () {public void windowclosing (WindowEvent e) {System.
Exit (0);
}
});
Aframe.add (applet, borderlayout.center);
Aframe.setsize (350,550);
Applet.init ();
Applet.start ();
Aframe.setvisible (TRUE); }
} ///:~
In Init (), note that loops traverse the entire array and add state and Peeker.status text fields to the page.
Once the blockable thread is created for the first time, each such thread automatically creates and starts its own peeker. So we'll see each peeker run before the blockable thread starts. This is important because when the blockable thread starts, part of the Peeker is blocked and stops running. To understand this will help us deepen our understanding of the concept of "blockage".