НАЗАД

JAVA. Часть 1.

Потоки и процессы в Java.

Для начала внесем ясность, что такое процессы и потоки. Процесс выполняется в среде, обеспечиваемой операционной системой, которая имеет собственный набор ресурсов и специально выделяет ресурсы для работы процесса.
Потоки находятся внутри процессов и используют ресурсы, которые были выделены для процесса. По сути, поток представляет собой часть программного кода, которые является частью процесса, и который может выполнятся параллельно с другими потоками процесса. Для обеспечения «защищенного» доступа к ресурсам процесса, потоки используют технологию синхронизации (об этом в другой статье).
Потоки применяются для обеспечения работы пользовательских интерфейсов. Дело в том, что программы выполняются последовательно. Раз программы выполняются последовательно, то при нажатии на клавише в пользовательском интерфейсе будет запущен некий программный код. И до завершения которого, пользовательский интерфейс будет не доступен пользователю. Полагаю, пользователь будет совсем не рад этому. Чтобы этого избежать, применяют потоки. При нажатии клавиши запускается поток с программным кодом. Программные код выполняется, но при этом пользовательский интерфейс доступен.
Каждый процесс имеет как минимум один поток. В Java, после создания процесса запускается главный поток с метода main(). Из главного метода могут быть запущены другие потоки, которые могут выполнятся даже при завершение работы главного потока.
Ниже приведен простой код создания потоков:

package SimpleTread001;
class Thread01 extends Thread{
    @Override
    public void run() {
        System.out.println("Hello from 001 tread");
    }
}
public class SimpleTread {
    static Thread01 thread001;
    public static void main(String[] args) {
        thread001 = new Thread01();
        thread001.start();
        System.out.println("The Main Tread is finished");
    }
}

В вышеприведенном примере показано создание и запуск простого потока. Сначала объявляется класс с блоком исполняемого кода. В классе переопределяется метод Run(). Данный метод содержит исполняемый код (вся логика работы здесь). В нашем случае выводится надпись "Hello from 001 tread".
В основном классе программы, в методе main() объявляются переменные объектов потока. Запуск потока выполняется методом start().
Потоки могут находится в нескольких состояниях:

Работа с приоритетами потока производится с помощью двух функций: Значения приоритетов могут быть только три: Синтаксис всех методов – Имя_потока.метод.
Метод stop() – должен завершать поток незамедлительно после выполнения. На данный момент объявлен устаревшим и не всегда работает как надо.
Метод suspend() – приостанавливает выполнение потока. Объявлен устаревшим.
Метод resume() – возобновляет выполнение потока. Объявлен устаревшим.
Метод Interruption() – работает с флагом прерывания. Является статическим методом, при вызове, возвращает значение флага прерывания того потока, из которого он был вызван. Этот метод позволяет потоку проверить свое состояние прерывания. При вызове, возвращает значение флага прерывания и сбрасывает его.
Метод bool isInterrupted() – проверяет, установлен ли флаг. Возвращает значение флага прерывания.
Метод sleep() – приостанавливает выполнение потока на заданное количество времени. Является статическим методом класса Thread, должен быть использован внутри конструкции try-catch.
Метод join() – обязывает один поток ждать завершения другого. Вызываемой метод в потоке обязывает главный поток или поток из которого был вызван поток, ждать завершения выполнения потока, из которого был вызван метод join(). Должен быть использован внутри конструкции try-catch.
Метод yield() – обязывает процессор переключится на обработку других потоков системы. Является статическим методом.
Метод setDeamon(true) - переводит поток в режим демона, т.е. когда завершиться основной поток, завершаются принудительно все потоки в режиме Демон.
Метод isDeamon() – выдает true, если поток в режиме демона или false, если поток не в режиме демона.
Метод Boolean isAlive() – возвращает значение true, если поток выполняется и false если нет.
Метод String getName() – получает имя потока.
Метод setName(String threadName) – задает имя потока.
Метод long getId() – возвращает идентификатор потока (уникальное число, которое присвоено потоку).
Метод static Thread Thread.currentThread() – возвращает объект потока, из которого он был вызван.
Ниже приведен пример работы с демонами.

package SimpleThread002
public class Example {
    private static class DeamonThread extends Thread{
    public DeamonThread(){
        setDeamon(true);
    }    
    @Override
    public void run(){
        while(true){
            try{
            Thread.sleep(1);
        }catch(InterruptedException e){
            e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) throws InterrupedException{
        Thread thread = new DeamonThread();
        Thread.start();
    }
}

Далее рассмотрим несколько способов запуска потоков. Смотрите пример ниже:

package thread03;
class Thread01 extends Thread{
    @Override
    public void run() {
        System.out.println("Hello from 001 tread");
    }
}
class Thread02 implements Runnable{
    @Override
    public void run() {
        System.out.println("Hello from 002 tread!");
    }
}
public class Thread03 {
    static Thread02 thread002;
    static Thread01 thread001;
    public static void main(String[] args) {
        thread002 = new Thread02();
        Thread thread004= new Thread(thread002);
        Thread thread005 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello from 005 tread");
            }
        });
        thread001 = new Thread01();
        thread004.start();
        thread005.start();
        thread001.start();
        thread005.join();
        System.out.println("The Main Tread is finished");
    }
}

Как видно из кода программы выше, запустить поток возможно несколькими способами. Непосредственно созданием объекта потока и командой start(). При создании объекта, переопределить непосредственно в скобках метод Run() или передать через скобки другой поток.
Важно отметить, что метод join() приименный в потоке thread005 не позволит завершиться главному потоку до завершения потока thread005.



Николай Ткаченко, 2015 г.