Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
41
Добавлен:
27.03.2015
Размер:
244.74 Кб
Скачать

Пакеты java.lang и java.util.concurrent Потоки и многопоточность

Вмомент запуска любого приложения с ним сопоставляется в точности один поток управления. Многие приложения целиком исполняются в этом единственном потоке.

Вплатформе Java с самого начала была заложена возможность образования дополнительных потоков управления, исполняемых параллельно (одновременно или квазиодновременно) в едином адресном пространстве

приложения.

Средства поддержки многопоточности, обеспечивающие все более удобные

и эффективные возможности, добавлялись в JDK 1.2 (класс java.lang.ThreadLocal), в JDK 1.3 (классы java.util.TimerTask и java.util.Timer), в JDK 1.5 (основные классы пакета java.util.concurrent), а затем в JDK 1.6 и 1.7 (классы и интерфейсы пакета java.util.concurrent).

Вначале рассмотрим использование базовых средств платформы Java:

интерфейсы:

java.lang.Runnable

классы

java.lang.Thread

java.lang.ThreadLocal

java.util.TimerTask

java.util.Timer

java.lang.ThreadGroup

Класс java.lang.Thread

Есть три возможности использования класса java.lang.Thread.

1. Можно просто создать свой дочерний класс на базе класса Thread и вызвать его метод start(). При этом фактически возникает новый поток и вызывается метод run().

Вот пример потока, просто выдающего обратный отсчет в секундах: public static void main( String[ ] args ) {

class ThreadTest extends Thread { int count = 4;

public void run( ){ while( --count > 0 ){

System.out.println( "Wait: " + count ); try {

Thread.sleep( 1000 );

} catch ( InterruptedException e ) { e.printStackTrace( ); }

}

System.out.println( "Start!" + " Thread Id: " + Thread.currentThread( ).getId( ) );

}

 

Main thread Id: 1

}

ThreadTest tt = new ThreadTest( );

Wait: 3

tt.start( );

Wait: 2

System.out.println( "Main thread Id: " + Thread.currentThread( ).getId( ) );

Wait: 1

}

Start! Thread Id: 8

Поля, конструкторы и методы класса java.lang.Thread (1)

public final NORM_PRIORITY

Нормальный приоритет

static int

 

 

public final MAX_PRIORITY

Максимальный приоритет

static int

 

 

public final MIN_PRIORITY

Минимальный приоритет

static int

 

 

public

Thread( )

Конструктор нового объекта Thread

public

Thread( Runnable target )

Конструктор нового объекта Thread с указанием объекта,

 

 

для которого будет вызываться метод run

public

Thread( Runnable target, String

Аналогично предыдущему, но дополнительно задается

 

name )

имя нового объекта Thread

public

Thread( String name )

Конструктор объекта Thread с указанием его имени

public

Thread( ThreadGroup group,

Конструктор нового объекта Thread с указанием группы

 

Runnable target )

потока и объекта, для которого вызывается метод run

public

Thread( ThreadGroup group,

Аналогично предыдущему, но дополнительно задается

 

Runnable target, String name )

имя нового объекта Thread

public

Thread( ThreadGroup group,

Конструктор нового объекта Thread с указанием группы

 

String name )

потока и имени объекта

Методы класса java.lang.Thread (2)

public static int

activeCount( )

Возвращает текущее количество активных потоков в группе,

 

 

 

к которой принадлежит поток

public void

checkAccesss( )

Разрешает текущему потоку изменять этот объект Thread

public int

countStackFrames( )

 

Возвращает количество фреймов в стеке (может быть

 

 

 

 

вызван только для потоков, приостановленных с помощью

 

 

 

метода suspend( ))

public static Thread

currentThread( )

Возвращает текущий работающий поток

public void

destroy( )

 

Принудительное завершение работы потока

public static void

dumpStack( )

Вывод на консоль текущего содержимого стека для отладки

public static int

enumerate( Thread

Заполняет указанный массив активными объектами Thread

 

tarray[] )

данной группы и всех ее подгрупп; возвращает количество

 

 

 

заполненных элементов массива

public final String

getName( )

Возвращает имя текущего потока

public final int

getPriority( )

Возвращает текущий приоритет потока

public final

getThreadGroup( )

Возвращает группу, к которой принадлежит поток

ThreadGroup

 

 

 

Поля и методы класса java.lang.Thread (3)

public void

interrupt( )

Прерывание выполнения метода sleep потока

public static

interrupted( )

Проверка, прервано ли выполнение текущего потока

boolean

 

 

 

public final

isAlive( )

Проверка, выполняется поток или нет (может спать или ждать

boolean

 

 

извещения)

public final

isDaemon( )

Проверка, является ли поток демоном Обычно потоки-демоны

boolean

 

 

создаются для обслуживания некритичных задач. Виртуальная

 

 

 

машина завершает свою работу, если завершились все потоки, не

 

 

 

являющиеся демонами. В этот момент демоны завершаются

 

 

 

принудительно

public boolean

isInterrupted( )

Проверка, прервано ли выполнение данного потока

public final void

join( )

Ожидание завершения указанного потока

public final void

join( long millis )

Ожидание завершения указанного потока в течение заданного

 

 

 

времени. Время задается в миллисекундах

public final void

join( long millis,

Ожидание завершения указанного потока в течение заданного

 

int nanos )

времени. Время задается в миллисекундах и наносекундах

public final void

resume( )

 

Возобновление выполнения временно приостановленного потока

 

public void

run( )

Метод вызывается неявно в том случае, если поток был создан как

 

 

 

объект с интерфейсом Runnable

Поля и методы класса java.lang.Thread (4)

public final void

setDaemon( boolean on )

Установка режима демона для потока

public final void

setName( String name )

Установка имени потока

public final void

setPriority( int

Установка приоритета потока

 

newPriority )

 

public static void

sleep( long millis )

Задержка выполнения потока на заданное время. Время

 

 

задается в миллисекундах

public static void

sleep( long millis, int

Задержка потока на заданное время. Время задается в

 

nanos )

миллисекундах и наносекундах

public void

start( )

Инициализация потока и запуск его на выполнение,

 

 

вызывается метод run

public final void

stop( )

Останов выполнения потока

public final void

stop( Throwable obj )

Аварийный останов выполнения потока с заданным

 

 

исключением

public final void

suspend( )

Приостановка выполнения потока

public String

toString( )

Строка, представляющая объект-поток

public static void

yield( )

Приостановка выполнения текущего потока для того,

 

 

чтобы управление было передано другому потоку

Класс java.lang.Thread, интерфейс Runnable

2. Можно реализовать интерфейс Runnable в своем классе, а затем создать объект класса Thread, передав конструктору этот объект как параметр. Этот способ используется, когда разрабатываемый класс должен быть наследником какого-либо другого класса (множественного наследования в Java нет):

public static void main( String[ ] args ) {

class ThreadTest extends java.lang.Object implements Runnable { int count = 4;

public void run( ){ while( --count > 0 ){

System.out.println( "Wait: " + count ); try {

Thread.sleep( 1000 );

} catch ( InterruptedException e ) { e.printStackTrace( ); }

}

System.out.println("Start!" + " Priority: " + Thread.currentThread( ).getPriority( ) );

}

 

}

 

 

new Thread( new ThreadTest( ) ).start();

Priorities: 1:5:10

System.out.println(" Priorities: "+Thread.MIN_PRIORITY +

Wait: 3

":" + Thread.NORM_PRIORITY +

Wait: 2

":"+Thread.MAX_PRIORITY );

Wait: 1

}

Start! Priority: 5

 

 

Классы java.util.TimerTask и java.util.Timer (1)

3. Часто в программе нужно выполнять какие-то действия (дальше будем их

называть задачами - Task) периодически или согласно расписанию. Можно создать дочерний класс на базе класса java.util.TimerTask, а затем создать объект класса java.util.Timer, установив нужный момент (или моменты) активации

задачи.

Класс TimerTask является абстрактным, и служит основой для всех выполняемых по расписанию задач.

Класс Timer обеспечивает создание и управление потоками, на которых выполняются эти задачи.

Пример: import java.util.*;

public class MyTask extends TimerTask { public void run( ) { System.out.println( "Запуск задачи" );

}

}

В данном случае задача сводится к выведению строки на экран.

Класс TimerTask реализует интерфейс java.lang.Runnable. Написанный метод должен вызываться из класса Timer.

Классы java.util.TimerTask и java.util.Timer (2)

После того, как задача запрограммирована, необходимо задать расписание ее выполнения. Для этого с помощью метода schedule() создается интерфейс класса Timer:

import java.util.*;

Timer timer = new Timer( ); TimerTask task = new MyTask( );

// Ждать десять секунд, прежде чем выполнить task( )...

timer.schedule( task, 10000 );

(или так: // Ждать пять секунд перед первым выполнением task, // а затем выполнять каждые 10 секунд

timer.schedule( task, 5000, 10000 );

)

Можно задать расписание четырех типов:

выполнять задачу в строго отведенное время (используется объект Date);

после некоторой задержки (в миллисекундах);

через определенные промежутки времени;

через определенные промежутки времени после заданного начального момента времени (реализуется с помощью метода scheduleAtFixedRate).

Классы java.util.TimerTask и java.util.Timer (3)

Каждый объект Timer создает в точности один фоновый поток. В этом потоке могут выполняться несколько задач, каждая по своему расписанию. Большинству приложений вполне достаточно одного таймера, но в принципе можно использовать любое их количество.

Остановить таймер и уничтожить его поток можно, вызвав метод cancel() объекта Timer. Нужно иметь в виду, что остановленный таймер уже не может быть перезапущен. При необходимости придется создать новый таймер и заново ввести расписание задач.

Timer использует безопасные потоки, это значит, что не нужно выполнять их синхронизацию при использовании одного и того же таймера из разных потоков.

Остановка задачи (и таймера, если задача является единственной у него) часто осуществляется изнутри метода run запущенной задачи. Вызов метода cancel() из метода run() гарантирует, что текущее выполнение задачи является последним.

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

Соседние файлы в папке Презентации по Java