Пример потока Java

Добро пожаловать в пример потока 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

  1. Потоки Java легче по сравнению с процессами, на создание потока требуется меньше времени и ресурсов.
  2. Потоки делят данные и код своего родительского процесса
  3. Переключение контекста между потоками обычно менее затратно, чем между процессами.
  4. Взаимодействие между потоками относительно проще, чем между процессами.

Java предоставляет два способа создания потока программно.

  1. Реализация интерфейса java.lang.Runnable.
  2. Расширение класса 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