Многопоточность в учебнике Java с примерами

Любое приложение может иметь несколько процессов (экземпляров). Каждый из этих процессов может быть назначен как один поток, так и несколько потоков.

В этом учебнике мы увидим, как выполнять несколько задач одновременно, а также узнавать больше о потоках и синхронизации между потоками.

В этом уроке мы узнаем,

Что такое одиночная тема?

Единственный поток – в основном легкий и самый маленький блок обработки. Java использует потоки, используя “класс темы”.

Существует два типа потоков – поток пользователей и поток демона (потоки демона используются, когда мы хотим очистить приложение и использоваться в фоновом режиме).

Когда приложение сначала начинается, создается пользовательский поток. Сообщаем, что мы можем создать много потоков пользователей и потоков демонов.

Пример одной темы:

Преимущества одиночной резьбы:

  • Уменьшает накладные расходы в приложении, поскольку один поток выполняется в системе
  • Кроме того, это снижает стоимость обслуживания приложения.

Что такое многопоточность?

Многопоточность в Java – это процесс одновременного выполнения двух или более потоков для максимального использования CPU.

Многопоточные приложения – это два или более потока одновременно; поэтому он также известен как параллелизм в Java. Эта многозадачность выполняется, когда несколько процессов имеют общие ресурсы, такие как процессор, память и т. Д.

Каждый поток проходит параллельно друг другу. Нити не выделяют отдельную область памяти; следовательно, он сохраняет память. Кроме того, переключение контекста между потоками занимает меньше времени.

Пример Multi thread:

Преимущества многопоточности:

  • Пользователи не блокируются, потому что потоки независимы, и мы можем выполнять несколько операций в разы
  • Таким образом, потоки независимы, другие потоки не будут затронуты, если один поток встретит исключение.

Жизненный цикл резьбы в Java

Жизненный цикл потока:

Существуют различные этапы жизненного цикла нити, как показано на диаграмме выше:

  1. новый
  2. Runnable
  3. Бег
  4. ждущий
  5. мертв
  6. Новое: наэтом этапе поток создается с использованием класса “Класс темы”. Он остается в этом состоянии, пока программа не запустит нить. Он также известен как рожденная нить.
  7. Runnable:На этой странице экземпляр потока вызывается с помощью метода start. Управление потоком предоставляется планировщику для завершения выполнения. Это зависит от планировщика, следует ли запускать поток.
  8. Выполнение:Когда поток начинает выполняться, состояние переходит в состояние “running”. Планировщик выбирает один поток из пула потоков и начинает выполнение в приложении.
  9. Ожидание:это состояние, когда поток должен ждать. Поскольку в приложении работает несколько потоков, существует потребность в синхронизации между потоками. Следовательно, один поток должен ждать, пока другой поток не будет выполнен. Следовательно, это состояние называется ожидающим.
  10. Dead:Это состояние, когда поток завершается. Поток находится в рабочем состоянии, и как только он завершит обработку, он находится в “мертвом состоянии”.

Некоторые из наиболее часто используемых методов для потоков:

метод Описание
Начало() Этот метод запускает выполнение потока, а JVM вызывает метод run () в потоке.
Сон (int миллисекунды) Этот метод заставляет поток спать, поэтому выполнение потока приостанавливается на миллисекунды, и после этого снова начинает выполняться поток. Это помогает синхронизировать потоки.
GetName () Он возвращает имя потока.
setPriority (int newpriority) Он изменяет приоритет потока.
Уступать () Это приводит к остановке текущего потока при остановке и выполнении других потоков.

Пример. В этом примере мы собираемся создать поток и изучить встроенные методы, доступные для потоков.

Объяснение кода:

Code Line 2: Мы создаем класс “thread_Example1”, который реализует интерфейс Runnable (он должен быть реализован любым классом, экземпляры которого предназначены для выполнения потоком).

Строка кода 4: она отменяет метод запуска интерфейса runnable, поскольку это необходимо для переопределения этого метода

Линия кода 6: Здесь мы определили основной метод, в котором мы начнем выполнение потока.

Code Line 7: Здесь мы создаем новое имя потока как “guruthread1”, создавая новый класс потока.

Кодовая строка 8: мы будем использовать метод “start” потока с использованием экземпляра “guruthread1”. Здесь начнется выполнение потока.

Code Line 10: Здесь мы используем метод “sleep” потока с использованием экземпляра “guruthread1”. Следовательно, поток будет спать в течение 1000 миллисекунд.

Код 9-14: Здесь мы поставили метод sleep в try catch block, так как проверено исключение, которое происходит, т.е. Прерванное исключение.

Строка кода 15: Здесь мы устанавливаем приоритет потока на 1 из того приоритета, который был

Строка кода 16: здесь мы получаем приоритет потока, используя getPriority ()

Строка кода 17: Здесь мы печатаем значение, полученное из getPriority

Строка кода 18: Здесь мы пишем текст, в котором работает поток.

Когда вы выполняете вышеуказанный код, вы получаете следующий результат:

Вывод:

5 – приоритет потока, а Thread Running – это текст, который является результатом нашего кода.

Синхронизация потоков Java

В многопоточности существует асинхронное поведение программ. Если один поток пишет некоторые данные, а другой поток, который одновременно считывает данные, может создать несоответствие в приложении.

Когда требуется доступ к общим ресурсам двумя или более потоками, используется подход синхронизации.

Java предоставила синхронизированные методы для реализации синхронизированного поведения.

В этом подходе, когда поток достигает внутри синхронизированного блока, ни один другой поток не может вызывать этот метод на одном и том же объекте. Все потоки должны ждать, пока этот поток не завершит синхронизированный блок и не выйдет из этого.

Таким образом, синхронизация помогает в многопоточном приложении. Один поток должен ждать, пока другой поток завершит выполнение, тогда другие потоки будут разрешены для выполнения.

Его можно записать в следующем виде:

Пример многопоточности Java

В этом примере мы возьмем два потока и выберем имена потока.

Example1:

Объяснение кода:

Code Line 3: Мы взяли класс GuruThread1, который реализует Runnable (он должен быть реализован любым классом, экземпляры которого предназначены для выполнения потоком).

Код 8: это основной метод класса

Кодовая строка 9: Здесь мы создаем экземпляр класса Thread и создаем экземпляр с именем “guruThread1” и создаем поток.

Code Line 10: Здесь мы создаем экземпляр класса Thread и создаем экземпляр с именем “guruThread2” и создаем поток.

Строка кода 11: Мы начинаем поток, т.е. guruThread1.

Линия кода 12: Мы начинаем нить, т.е. guruThread2.

Строка кода 13: вывод текста в виде “Названия потоков следующие:”

Строка 14: получение имени потока 1 с использованием метода getName () класса потока.

Строка кода 15: Получение имени потока 2 с использованием метода getName () класса потока.

Когда вы выполняете вышеуказанный код, вы получаете следующий результат:

Вывод:

Названия имен выводятся здесь как

  • Guru1
  • Guru2

Пример 2:

В этом примере мы узнаем об переопределении методов run () и start () метода runnable interface и создадим два потока этого класса и выполним их соответственно.

Кроме того, мы принимаем два класса,

  • Один, который будет реализовывать исполняемый интерфейс и
  • Другой, который будет иметь основной метод и выполнить соответственно.

 

Объяснение кода:

Code Line 2: Здесь мы берем класс GuruThread2, который будет иметь в нем основной метод.

Кодовая строка 4: Здесь мы берем основной метод класса.

Линия кода 6-7: Здесь мы создаем экземпляр класса GuruThread3 (который создается в нижних строках кода) как “threadguru1”, и мы начинаем поток.

Code Line 8-9: Здесь мы создаем еще один экземпляр класса GuruThread3 (который создается в нижних строках кода) как “threadguru2”, и мы начинаем поток.

Code Line 11: Здесь мы создаем класс GuruThread3, который реализует исполняемый интерфейс (он должен быть реализован любым классом, экземпляры которого предназначены для выполнения потоком).

Строка кода 13-14: мы берем две переменные класса, из которых один относится к типу потока типов и к другому классу строк.

Строка кода 15-18: мы переопределяем конструктор GuruThread3, который принимает один аргумент как тип строки (который является именем нитей), который присваивается переменной класса guruname, и, следовательно, имя потока сохраняется.

Code Line 20: Здесь мы переопределяем метод run () интерфейса runnable.

Код 21: мы выводим имя потока с помощью инструкции println.

Строка кода 22-31: Здесь мы используем цикл for с инициализацией счетчика, равным 0, и он должен быть не менее 4 (мы можем взять любое число, поэтому здесь цикл будет выполняться 4 раза) и увеличивать счетчик. Мы печатаем имя потока, а также сокращаем поток в течение 1000 миллисекунд в блоке try-catch, поскольку метод sleep поднял проверенное исключение.

Линия кода 33: Здесь мы переопределяем метод запуска интерфейса runnable.

Строка кода 35: Мы выводим текст “Thread started”.

Строка кода 36-40: Здесь мы принимаем условие if, чтобы проверить, имеет ли в нем значение переменной guruthread или нет. Если его значение null, мы создаем экземпляр с использованием класса thread, который принимает имя в качестве параметра (значение для которого было назначено в конструкторе). После этого поток запускается с использованием метода start ().

Когда вы выполняете вышеуказанный код, вы получаете следующий результат:

Выход :

Есть два потока, поэтому мы получаем два раза сообщение “Thread started”.

Мы получаем имена потока, как мы их выводили.

Он переходит в цикл, где мы печатаем счетчик и имя потока, а счетчик начинается с 0.

Цикл выполняется три раза, а между потоком спадает 1000 миллисекунд.

Следовательно, во-первых, мы получаем guru1, затем guru2, затем снова guru2, потому что поток спит здесь в течение 1000 миллисекунд, а затем следующий guru1 и снова guru1, поток спит в течение 1000 миллисекунд, поэтому мы получаем guru2, а затем guru1.

Резюме :

В этом уроке мы увидели многопоточные приложения на Java и как использовать один и несколько потоков.

  • При многопоточности пользователи не блокируются, так как потоки независимы и могут выполнять несколько операций во времени
  • Различные этапы жизненного цикла нити,
    • новый
    • Runnable
    • Бег
    • ждущий
    • мертв
  • Мы также узнали о синхронизации между потоками, которые помогают приложению работать бесперебойно.
  • Многопоточность упрощает выполнение многих задач.
0 ответы

Ответить

Хотите присоединиться к обсуждению?
Не стесняйтесь вносить свой вклад!

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *