Думай на Java

       

Установка блокировки


Блокированное состояние одно из наиболее интересных и стоит последующего рассмотрения. Процесс может стать блокированным в пяти случаях:

  • Установка процесса в спящее состояние посредством вызова sleep(milliseconds), в этом случае он не будет выполняться определенный промежуток времени.
  • Приостановка выполнения процесса вызовом suspend( ). Он не будет выполняться до тех пор, пока не получит сообщение resume( ) (что запрещено в Java 2, и дальше будет описано).
  • Приостановка выполнения с помощью wait( ). Процесс не будет повторно запущен на выполнение до тех, пор пока не получит сообщение notify( ) или notifyAll( ). (Это похоже на пункт 2, но существуют определенные различия, которые будут также показаны.)
  • Процесс ожидает завершения каких-то операций ввода/вывода.
  • Процесс пытается вызвать synchronized метод другого объекта и блокировка этого объекта невозможна.
  • Можно также вызвать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, что означает необходимость в отсутствии блокировки объекта для их выполнения.


    Содержание раздела