Добро пожаловать в пример потока Java. Процесс и Поток – две основные единицы выполнения. При программировании параллельности больше внимания уделяется потокам Java.
Процесс
A process is a self contained execution environment and it can be seen as a program or application. However a program itself contains multiple processes inside it. Java runtime environment runs as a single process which contains different classes and programs as processes.
Поток
Поток можно назвать легковесным процессом. Для создания потока требуется меньше ресурсов, и он существует в процессе, разделяя его ресурсы.
Пример потока Java
Каждое приложение на Java имеет как минимум один поток – основной поток. Хотя существует много других потоков Java, работающих в фоновом режиме, таких как управление памятью, управление системой, обработка сигналов и т. д. Однако с точки зрения приложения основной поток – это первый поток Java, и мы можем создавать несколько потоков из него. Многопоточность означает выполнение двух или более потоков одновременно в одной программе. Процессор с одним ядром компьютера может выполнять только один поток за раз, а выделение времени – это функция ОС для распределения времени процессора между различными процессами и потоками.
Преимущества потоков Java
- Потоки Java легче по сравнению с процессами, на создание потока требуется меньше времени и ресурсов.
- Потоки делят данные и код своего родительского процесса
- Переключение контекста между потоками обычно менее затратно, чем между процессами.
- Взаимодействие между потоками относительно проще, чем между процессами.
Java предоставляет два способа создания потока программно.
- Реализация интерфейса java.lang.Runnable.
- Расширение класса java.lang.Thread.
Пример потока Java – реализация интерфейса Runnable
Чтобы сделать класс исполняемым, мы можем реализовать интерфейс java.lang.Runnable и предоставить реализацию в методе public void run()
. Для использования этого класса как потока нам нужно создать объект Thread, передав объект этого класса Runnable, и затем вызвать метод start()
для выполнения метода run()
в отдельном потоке. Вот пример потока Java с реализацией интерфейса Runnable.
package com.journaldev.threads;
public class HeavyWorkRunnable implements Runnable {
@Override
public void run() {
System.out.println("Doing heavy processing - START "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
// Получение подключения к базе данных, удаление неиспользуемых данных из БД
doDBProcessing();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Doing heavy processing - END "+Thread.currentThread().getName());
}
private void doDBProcessing() throws InterruptedException {
Thread.sleep(5000);
}
}
Пример потока Java – расширение класса Thread
Мы можем расширить класс java.lang.Thread, чтобы создать собственный класс потока Java и переопределить метод run()
. Затем мы можем создать его объект и вызвать метод start()
для выполнения метода run нашего пользовательского класса потока Java. Вот простой пример потока Java, показывающий, как расширить класс Thread.
package com.journaldev.threads;
public class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println("MyThread - START "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
// Получение подключения к базе данных, удаление неиспользуемых данных из БД
doDBProcessing();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("MyThread - END "+Thread.currentThread().getName());
}
private void doDBProcessing() throws InterruptedException {
Thread.sleep(5000);
}
}
Вот тестовая программа, показывающая, как создать поток Java и выполнить его.
package com.journaldev.threads;
public class ThreadRunExample {
public static void main(String[] args){
Thread t1 = new Thread(new HeavyWorkRunnable(), "t1");
Thread t2 = new Thread(new HeavyWorkRunnable(), "t2");
System.out.println("Starting Runnable threads");
t1.start();
t2.start();
System.out.println("Runnable Threads has been started");
Thread t3 = new MyThread("t3");
Thread t4 = new MyThread("t4");
System.out.println("Starting MyThreads");
t3.start();
t4.start();
System.out.println("MyThreads has been started");
}
}
Результат вышеуказанной программы примера потока Java:
Starting Runnable threads
Runnable Threads has been started
Doing heavy processing - START t1
Doing heavy processing - START t2
Starting MyThreads
MyThread - START Thread-0
MyThreads has been started
MyThread - START Thread-1
Doing heavy processing - END t2
MyThread - END Thread-1
MyThread - END Thread-0
Doing heavy processing - END t1
Как только мы запускаем любой поток, его выполнение зависит от реализации ОС по временному срезу, и мы не можем контролировать их выполнение. Однако мы можем установить приоритет потоков, но даже это не гарантирует, что поток с более высоким приоритетом будет выполнен первым. Запустите вышеуказанную программу несколько раз, и вы увидите, что нет никакого порядка начала и завершения потоков.
Runnable vs Thread
Если ваш класс предоставляет больше функциональности, чем просто выполнение как поток, вы должны реализовать интерфейс Runnable для возможности запуска в виде потока. Если единственная цель вашего класса – выполнение как поток, вы можете расширить класс Thread. Реализация интерфейса Runnable предпочтительна, поскольку Java поддерживает реализацию нескольких интерфейсов. Если вы расширяете класс Thread, вы не можете расширить другие классы. Совет: Как вы заметили, поток не возвращает никакого значения, но что, если мы хотим, чтобы наш поток выполнял некоторую обработку, а затем возвращал результат нашей клиентской программе? Проверьте наш Java Callable Future. Обновление: С Java 8 и далее, интерфейс Runnable является функциональным интерфейсом, и мы можем использовать лямбда-выражения для его реализации вместо использования анонимного класса. Дополнительные сведения можно найти в Java 8 Functional Interfaces.
Source:
https://www.digitalocean.com/community/tutorials/java-thread-example