Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

public static void main(String[] args)




3. При нажатии кнопки " Start Counting", actionPerformed о запускается внутриEDT. И EDT теперь полностью захвачен вычислительным циклом. Другими словами, пока происходят вычисления в цикле, EDT занят, и не может обрабатывать другие события (т. е., нажатие кнопки " Stop Counting" или закрытие окна), а также обновновление формы невозможно до окончания цикла счета, только тогда EDT освобждается. В результате вся форма и ее элементы " заморожены" до окончания цикла.

 

Ркеомендуется запускать GUI В EDT черезВЫЗОВ invokeLater (), потому что множество GUI компонент не являются гарантированнро потокобезопасными (thread-safe). Распределение доступа к GUI компонентам в едином потоке гарантирует потокобезопасность. Предположим, что мы запустили конструктор напрямую в main () (используя поток " main" ):

public static void main(String[] args)

{ new UnresponsiveUi();

}

 

Последовательность действий будет следующей:

1. Метод main () стартует в потоке " main".

2. Новый поток " AWT-Windows" (Daemon thread) запускается командой-конструктором " new UnresponsiveUi ()" (из-за" extends JFrame" ).

3. После выполнения " setVisibie (true)" создаются два других потока - " AWT-Shutdown" и " AWT-EventQueue-0" (i. e., the EDT).

4. Поток " main" " живет" и после того, как метод main () завершается. Запукается новый поток с именем " DestroyJavaVM".

5. Запущены 4 потока - " AWT-Windows", " AWT-Shutdown", " AWT- EventQueue-0 (EDT)"  и " DestroyJavaVM".

6.  Нажатием кнопки " Start Counting" запускается actionPerformed() внутри EDT.

В предыдущем случае планировщик EDT запускается сразу методом invokeLater(), тогда как в последнем примере EDT стартует после setVisibie().

Пример 5. 2. 2.

Изменим обработчик кнопки " Start Counting", запустив вычисления в отдельном потоке:

JButton btnStart = new JButton(" Start Counting" );

cp. add(btnStart);

btnStart. addActionListener(new ActionListener() {

    @Override

    public void actionPerformed(ActionEvent evt) {

       stop = false;

 // Create a new Thread to do the counting

       Thread t = new Thread() {

          @Override

          public void run() { 

// override the run() for the running behaviors*/

             for (int i = 0; i < 100000; ++i) {

                if (stop) break;

                tfCount. setText(count + " " );

                ++count;

// Suspend this thread via sleep() and yield control to other threads. Also provide the necessary delay.

                try {

                   sleep(10); // milliseconds

                } catch (InterruptedException ex) {}

             }

          }

       };

       t. start(); // call back run()

    }

});

 

Создается новый поток с помощью анонимного вложенного класса. Переопределяем run() метод, который выполняет наши вычисления. Метод start() запускает run() на выполнение в своем собственном потоке.

Способность к реагированию, таким образом, несколько улучшается. Но необходимое значение подсчета все еще не отображается как следует, и все еще существует задержка в ответ на нажатие кнопки " STOP". Это происходит потому, что поток подсчета не уступает добровольно управления потоку-планировщику EDT - " замороженный" EDT не может обновлять форму и реагировать на события. Однако, JVM может заставить поток подсчета уступить управление согласно алгоритму-планировщику, что в результате выливается в задержку обновления формы.

Пример 5. 2. 3.

Изменим программу, добавив вызов метода sleep() обработчику кнопки " Start Counting":

sleep() дает возможность циклу подсчета уступить (yield) управление потоку планировщику (event-dispatching thread) для обновления формы и отклик на кнопку " STOP". Программа подсчета теперь будет работать так, как нужно, sleep () обеспечит необходимую задержку.

btnStart. addActionListener(new ActionListener() {

    @Override

    public void actionPerformed(ActionEvent evt) {

       stop = false;

       // Create a new Thread to do the counting

       Thread t = new Thread() {

          @Override

          public void run() { // override the run() for the running behaviors*/

             for (int i = 0; i < 100000; ++i) {

                if (stop) break;

                tfCount. setText(count + " " );

                ++count;

// Приостановка потока методом sleep() передача управления другим //потокам. Обеспечение необходимой задержки в миллисекундах.

                try {

                   sleep(10); // milliseconds

                } catch (InterruptedException ex) {}

             }

          }

       };

       t. start(); // call back run()

    }

});

 

Метод sleep() приостанавливает текущий поток и устанавливает его в состояние ожидания на указанное количество миллисекунд. Теперь может быть запущен другой поток  (sleep() может быть прерван путем запуска метода interrupt() этого потока, что вызывает InterruptedException()

В этом случае, поток, созданный ля вычислений уступает (yields) управление добровольно другим потоком после каждого счета (путем установки  " sleep(10)" ). Это позволяет потоку-планировщику обновлять окно при каждом нажатии на кнопку " STOP".

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...