Установка блокировки
Блокированное состояние одно из наиболее интересных и стоит последующего рассмотрения. Процесс может стать блокированным в пяти случаях:
Можно также вызватьyield( ) (один из методов класса Thread), чтобы добровольно передать свой квант времени другим процессам. Однако, то же самое произойдет если планировщик решит, что ваш процесс уже выполняется достаточно долго и передать управление другому. Таким образом, ничего не мешает планировщику покинуть процесс и перейти на другой. Когда процесс блокирован, то существуют какие-то причины, корые мешают ему выполняться.
Следующий пример показывает все пять способов установки блокировки. Все они реализованы в единственном файле под названием Blocking.java, но будут рассмотрены здесь частично. (Вы столкнетесь с "продолженным" и "продолжающим" тэгами, что позволяет средству изъятия кода сложить все это вместе.)
В связи с тем, что данный пример показывает некоторые запрещенные (deprecated) при компиляции будет выдано соответствующее сообщение.
В начале основная программы:
//: c14:Blocking.java
// Demonstrates the various ways a thread
// can be blocked.
// <applet code=Blocking width=350 height=550>
// </applet>
import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import com.bruceeckel.swing.*;
//////////// The basic framework ///////////
class Blockable extends Thread { private Peeker peeker; protected JTextField state = new JTextField(30); 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 JTextField status = new JTextField(30); 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); } catch(InterruptedException e) { System.err.println("Interrupted"); } } } } ///:Continued
Предполагается, что класс Blockable будет базовым для всех остальных классов в данном примере, который демонстрирует блокировку. Объект Blockable содержит JTextField называемое state, используемое для показа информации об объекте. Метод, который выводит эту информацию - update(). Как видно, он использует getClass().getName() для получения имени класса вместо простого его вывода; это сделанно из-за того, что update() не может знать действительное имя объекта вызвавшего его поскольку этот класс наследник от Blockable.
int i это индикатор изменений в Blockable, который увеличивает свое значение через метод run() наследуемого класса.
Также есть процесс класса Peeker, который запускается для каждого объекта Blockable и его работа заключается в наблюдении за изменением переменной i в ассоциированном с ним объекте Blockable через вызов read() и выводом значения в его status JTextField поле. Вот что важно: оба метода read() и update() являются synchronized, что означает необходимость в отсутствии блокировки объекта для их выполнения.