Рубрики
Без рубрики

Как начать работу с многопоточностью в Java

Как начать работу с многопоточностью в Java. С тегами java, учебник, новички, темы.

Этот пост был первоначально опубликован в Этот пост был первоначально опубликован в

Поток – это легкий процесс. В любом процессе может быть запущено несколько потоков.

Например, в веб-браузере у нас может быть один поток, который будет загружать пользовательский интерфейс, и у нас может быть еще один поток, который фактически повторно отобразит все данные, которые необходимо отобразить в пользовательском интерфейсе.

Многопоточность позволяет нам запускать несколько потоков одновременно.

Например, в веб-браузере у нас может быть поток on, который обрабатывает пользовательский интерфейс, и параллельно у нас может быть еще один поток, который извлекает данные для отображения.

Таким образом, многопоточность повышает быстродействие системы.

Параллелизм в контексте потоков позволяет нам запускать несколько потоков одновременно.

Но действительно ли потоки выполняются одновременно?

Одноядерные Системы

Планировщик потоков , предоставляемый JVM, решает, какой поток выполняется в любой момент времени. Планировщик выделяет небольшой временной отрезок для каждого потока.

Таким образом, в любой момент времени у нас есть только поток, который фактически выполняется в процессоре. Но из-за сокращения времени у нас возникает ощущение, что одновременно выполняется несколько потоков.

Многоядерные Системы

Даже в многоядерных системах задействован планировщик потоков. Но поскольку у нас несколько ядер, на самом деле у нас может быть несколько потоков, запущенных в одно и то же время.

Например, если у нас двухъядерная система, то у нас может быть 2 потока, запущенных в одно и то же время. Первый поток будет выполняться в первом ядре, а второй поток будет выполняться во втором ядре.

Многопоточность позволяет нам повысить быстродействие Системы.

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

Так одновременное выполнение разных частей программы в разных потоках помогает повысить быстродействие системы.

Мы можем создавать потоки в java, используя следующее

  • Расширение класса потоков
  • Реализация управляемого интерфейса
  • Реализация вызываемого интерфейса
  • Используя платформу Executor вместе с выполняемыми и вызываемыми задачами

Мы рассмотрим Вызываемые объекты и фреймворк Executor в отдельном блоге. В этой статье я буду в основном сосредоточен на расширении класса Thread и реализации интерфейса Runnable.

Расширение класса потоков

Чтобы создать фрагмент кода, который можно запускать в потоке, мы создаем класс, а затем расширяем Thread Задача, выполняемая этим фрагментом кода, должна быть помещена в функцию run() . Задача, выполняемая этим фрагментом кода, должна быть помещена в функцию run() . Worker – это класс, который расширяет Класс Thread , и задача печати чисел от 0 до 5 выполняется внутри функции run()

class Worker extends Thread {

    @Override
    public void run() {
        for (int i = 0; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }

}

В приведенном выше коде Thread.currentThread().getName() используется для получения имени текущего потока, в котором выполняется код.

Для того, чтобы создать Нить , нам просто нужно создать экземпляр рабочего класса. И затем мы можем запустить поток, используя функцию start() .

public class ThreadClassDemo {
    public static void main(String[] args) {
        Thread t1 = new Worker();
        Thread t2 = new Worker();
        Thread t3 = new Worker();
        t1.start();
        t2.start();
        t3.start();

    }
}

В приведенном выше коде мы создаем 3 потока t1, t2 и t3 из рабочего класса. Затем мы запускаем потоки с помощью функции start() .

Вот окончательный код для создания потока путем расширения класса Thread

class Worker extends Thread {

    @Override
    public void run() {
        for (int i = 0; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }

}

public class ThreadClassDemo {
    public static void main(String[] args) {
        Thread t1 = new Worker();
        Thread t2 = new Worker();
        Thread t3 = new Worker();
        t1.start();
        t2.start();
        t3.start();

    }
}

Вот результат, который мы получаем, выполнив приведенный выше код

Видно, что все 3 потока напечатали числа от 0 до 5.

Из выходных данных ясно видно, что 3 потока не выполняются в какой-либо определенной последовательности

Реализация управляемого интерфейса

Чтобы создать фрагмент кода, который можно запускать в потоке, мы создаем класс, а затем реализуем Работоспособный Интерфейс. Задача, выполняемая этим фрагментом кода, должна быть помещена в функцию run() . В приведенном ниже коде вы можете видеть, что Runnable Worker – это класс, который реализует Работоспособный Интерфейс, и задача печати чисел от 0 до 4 выполняется внутри функции run() .

class RunnableWorker implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i <= 4; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }

}

Чтобы создать поток, сначала нам нужно создать экземпляр Runnable Worker , который реализует Работоспособный Интерфейс.

Затем мы можем создать новый поток, создав экземпляр класса Thread и передав экземпляр Runnable Worker в качестве аргумента. Это показано в приведенном ниже коде

public class RunnableInterfaceDemo {

    public static void main(String[] args) {
        Runnable r = new RunnableWorker();
        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        Thread t3 = new Thread(r);

        t1.start();
        t2.start();
        t3.start();

    }

}

Приведенный выше код создает исполняемый экземпляр r. Затем он создает 3 потока t1, t2 и t3 и передает r |/в качестве аргумента 3 потокам. Затем функция start() используется для запуска всех 3 потоков.

Вот полный код для создания потока путем реализации интерфейса Runnable

class RunnableWorker implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i <= 4; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }

}

public class RunnableInterfaceDemo {

    public static void main(String[] args) {
        Runnable r = new RunnableWorker();
        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        Thread t3 = new Thread(r);

        t1.start();
        t2.start();
        t3.start();

    }

}

Запустив приведенный выше код, мы получим следующий результат. Последовательность вывода будет меняться при каждом запуске кода.

Реализация интерфейса Runnable – лучший вариант, чем расширение класса Thread, поскольку мы можем расширить только один класс, но мы можем реализовать несколько интерфейсов в java.

Управляемый интерфейс в Java 8

В java 8 выполняемый интерфейс становится Функциональный интерфейс поскольку он имеет только одну функцию run() .

Приведенный ниже код показывает, как мы можем создать исполняемый экземпляр в java 8.

public class RunnableFunctionalInterfaceDemo {

    public static void main(String[] args) {

        Runnable r = () -> {
            for (int i = 0; i <= 4; i++) {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        };

        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        Thread t3 = new Thread(r);

        t1.start();
        t2.start();
        t3.start();
    }

}

Здесь вместо создания класса и последующей реализации интерфейса Runnable мы можем напрямую использовать лямбда-выражение для создания экземпляра Runnable, как показано ниже

Runnable r = () -> {
        for (int i = 0; i <= 4; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    };

Код в этой статье доступен в следующем репозитории github Код в этой статье доступен в следующем репозитории github

Теперь вы знаете, как создавать потоки, расширяя класс Thread и реализуя интерфейс Runnable.

Я расскажу о жизненном цикле потоков и проблемах при использовании потоков в моем следующем сообщении в блоге.

Не стесняйтесь связаться со мной в LinkedIn или подписаться на меня в Twitter.

Если вам понравился этот пост, вы можете зайти на мой сайт https://adityasridhar.com для других подобных сообщений

Оригинал: “https://dev.to/adityasridhar/how-to-get-started-with-multithreading-in-java-1b74”