Java Определение, создание и запуск потоков
Вступление
Одной из самых привлекательных функций в Java является поддержка простого программирования потоков. Java обеспечивает встроенную поддержку многопоточного программирования. Многопоточная программа содержит две или более частей, которые могут работать одновременно. Каждая часть такой программы называется потоком, и каждый поток определяет отдельный путь выполнения. Таким образом, мы можем сказать, что многопоточность является специализированной формой многозадачности.
Формальное определение потока: Поток - это базовый процессор, которому операционная система выделяет процессорное время, и несколько процессов могут выполнять код внутри процесса. Поток иногда называют облегченным процессом или контекстом выполнения
Представьте себе онлайн-заявку на бронирование билетов с множеством сложных возможностей. Одна из его функций - «поиск билетов на поезд / рейс из источника и пункта назначения», другая - «проверка цен и доступности», а третья трудоемкая операция - «бронирование билетов для нескольких клиентов одновременно».
В однопоточной среде выполнения эти действия выполняются одно за другим. Следующее действие может произойти только после завершения предыдущего. Если бронирование билета занимает 10 минут, то другие пользователи должны ждать своей операции поиска или операции бронирования. Такое приложение приведет к трате времени и клиентов. Чтобы избежать подобных проблем, в Java предусмотрены функции многопоточности, позволяющие выполнять несколько операций одновременно и быстрее реагировать на запросы пользователей. Многопоточность позволяет вам писать очень эффективные программы, максимально использующие ЦП, поскольку время простоя может быть сведено к минимуму.
Определение темы
В самом общем смысле вы создаете поток, создавая экземпляр объекта типа Thread.
Java определяет два способа, которыми это может быть достигнуто:
- Вы можете реализовать интерфейс Runnable.
- Вы можете расширить класс Thread
Реализация Runnable
Самый простой способ создать поток - создать класс, реализующий интерфейс Runnable. Runnable абстрагирует единицу исполняемого кода. Вы можете создать поток для любого объекта, который реализует Runnable. Для реализации Runnable класс должен реализовывать только один метод run (), который объявлен так:
public void run ()
Внутри run () вы определите код, который составляет новый поток. Важно понимать, что run () может вызывать другие методы, использовать другие классы и объявлять переменные, так же как и основной поток. Единственное отличие состоит в том, что run () устанавливает точку входа для другого параллельного потока выполнения в вашей программе. Этот поток закончится, когда run () вернется.
Класс MyRunnableThread реализует Runnable { public void run () { System.out.println («Важное задание в MyRunnableThread»); } }
Расширение java.lang.Thread
Самый простой способ определить код для запуска в отдельном потоке - это
- Расширьте класс java.lang.Thread.
- Переопределите метод run ().
Это выглядит так:
classMyThread расширяет поток { public void run () { System.out.println («Важное задание в MyThread»); } }
Ограничение этого подхода (помимо того, что в большинстве случаев это плохой выбор дизайна) заключается в том, что если вы расширяете Thread, вы не можете расширять что-либо еще. И дело не в том, что вам действительно нужно это наследуемое поведение класса Thread, потому что для того, чтобы использовать поток, вам все равно нужно его создать.
Создание темы
Помните, что каждый поток выполнения начинается как экземпляр класса Thread. Независимо от того, находится ли ваш метод run () в подклассе Thread или в классе реализации Runnable, вам все равно нужен объект Thread для выполнения этой работы.
Если у вас есть второй подход (расширение класса Thread): реализация будет простой
MyThread thread = new MyThread ();
Если вы реализуете Runnable, создание экземпляра будет лишь немного менее простым.
Чтобы создать экземпляр класса Runnable:
MyRunnableThreadmyRunnable = new MyRunnableThread (); Тема потока = новая тема (myRunnable); // Передаем ваш Runnable в поток
Назначение одной и той же цели нескольким потокам означает, что несколько потоков выполнения будут выполнять одно и то же задание (и что одно и то же задание будет выполняться несколько раз).
Конструкторы классов потоков
- Нить() :
Конструктор по умолчанию - для создания потока с именем и приоритетом по умолчанию
- Thread (Runnable target)
Этот конструктор создаст поток из запускаемого объекта.
- Thread (Runnable target, String name)
Этот конструктор создаст поток из запускаемого объекта с именем, переданным во втором аргументе.
- Тема (строковое имя)
Этот конструктор создаст поток с именем согласно переданному аргументу.
Итак, теперь мы создали экземпляр Thread, и он знает, какой метод run () вызывать. Но пока ничего не происходит. На данный момент все, что у нас есть, это простой старый Java-объект типа Thread. Это еще не нить казни. Чтобы получить реальный поток - новый стек вызовов - нам все еще нужно запустить поток.
Начало темы
Вы создали объект Thread, и он знает свою цель (либо значение before-inRunnable, либо само себя, если вы расширили класс Thread). Теперь пришло время реализовать весь поток - запустить новый стек вызовов. Это так просто, что вряд ли заслуживает своего подзаголовка:
t.start ();
До вызова start () в экземпляре Thread говорят, что поток находится в новом состоянии. Существуют различные состояния потоков, которые мы рассмотрим в следующем уроке.
Когда мы вызываем метод t.start (), происходит следующее:
- Начинается новый поток выполнения (с новым стеком вызовов).
- Поток переходит из нового состояния в работоспособное состояние.
- Когда поток получает возможность выполнения, запускается его целевой метод run ().
В следующем примере демонстрируется то, что мы уже рассмотрели - определение, создание экземпляра и запуск потока: в нижеприведенной Java-программе мы не реализуем взаимодействие или синхронизацию потоков, поскольку эти выходные данные могут зависеть от механизма планирования операционной системы и версии JDK.
Мы создаем два потока t1 и t2 объекта класса MyRunnable. Начиная оба потока, каждый поток печатает имя потока в цикле.
Java-код (MyRunnable.java)
package mythreading;
public class MyRunnable implements Runnable{
@Override
public void run() {
for(int x =1; x < 10; x++) {
System.out.println("MyRunnable running for Thread Name: " + Thread.currentThread().getName());
}
}
}
Java-код (TestMyRunnable.java)
package mythreading;
public class TestMyRunnable {
public static void main (String [] args) {
MyRunnable myrunnable = new MyRunnable();
//Passing myrunnable object to Thread class constructor
Thread t1 = new Thread(myrunnable);
t1.setName("Amit-1 Thread");
//Starting Thread t1
t1.start();
Thread t2 = new Thread(myrunnable);
t2.setName("Amit-2 Thread");
t2.start();
}
}
Выход:
Резюме:
- Потоки можно создавать, расширяя Thread и переопределяя открытый метод void run ()
- Объекты Thread также можно создавать, вызывая конструктор Thread, который принимает аргумент Runnable. Говорят, что объект Runnable является целью потока.
- Вы можете вызвать start () для объекта Thread только один раз. Если start () вызывается более одного раза для объекта Thread, он генерирует исключение времени выполнения.
- Каждый поток имеет свой собственный стек вызовов, который хранит состояние выполнения потока
- Когда объект Thread создается, он не становится потоком выполнения до тех пор, пока не будет вызван его метод start (). Когда объект Thread существует, но еще не запущен, он находится в новом состоянии и не считается живым.
Редактор кода Java:
Предыдущий: Java Utility Class
Далее: Состояния потоков Java и переходы
Новый контент: Composer: менеджер зависимостей для PHP , R программирования