Багатопотоковість на Java: Як розпочати роботу з потоками

Що таке нитка?

Нитка - це легкий процес. У будь-якому процесі може бути запущено кілька потоків.

Наприклад, у веб-браузері ми можемо мати один потік, який завантажує користувальницький інтерфейс, і інший потік, який фактично отримуватиме всі дані, які потрібно відображати в цьому інтерфейсі.

Що таке MultiThreading?

Багатопотоковість дозволяє нам запускати кілька потоків одночасно.

Наприклад, у веб-браузері ми можемо мати один потік, який обробляє користувальницький інтерфейс, і паралельно ми можемо мати інший потік, який отримує дані для відображення.

Отже, багатопотоковість покращує швидкість реагування системи.

Що таке паралельність?

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

Але чи справді потоки працюють одночасно?

Одноядерні системи

Планувальник потоків забезпечується JVM вирішує , який потік працює в будь-який момент часу. Планувальник надає невеликий інтервал часу кожному потоку.

Отже, у будь-який момент ми маємо лише один потік, який насправді працює в процесорі. Але через час нарізки у нас складається відчуття, що одночасно працює декілька потоків.

Багатоядерні системи

Навіть у декількох основних системах бере участь планувальник потоків. Але оскільки у нас кілька ядер, ми можемо мати кілька потоків, що працюють одночасно.

Наприклад, якщо у нас є двоядерна система, то ми можемо мати 2 потоки, що працюють одночасно. Перший потік буде працювати в першому ядрі, а другий потік - у другому ядрі.

Навіщо потрібна багатопотоковість?

Багатопотоковість дозволяє нам покращити швидкість реагування системи.

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

Отже, запуск різних частин програми в різних потоках одночасно допомагає поліпшити реакцію системи.

Як писати багатопотокові програми на Java

Ми можемо створювати потоки в Java, використовуючи наступне

  • Розширення класу потоків
  • Реалізація запущеного інтерфейсу
  • Реалізація інтерфейсу, що викликається
  • Використовуючи фреймворк виконавця разом із виконуваними та викликаними завданнями

Ми розглянемо виклики та структуру виконавця в окремому блозі. У цій статті я зосереджуватимусь головним чином на розширенні класу потоків та реалізації запущеного інтерфейсу.

Розширення класу потоків

Для того, щоб створити фрагмент коду, який можна запускати в потоці, ми створюємо клас, а потім розширюємо клас потоку . Завдання, яке виконує цей шматок коду, потрібно помістити у функцію run () .

У наведеному нижче коді ви можете бачити, що worker - це клас, який розширює клас потоку , і завдання друку номерів від 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 () використовується для отримання імені поточного потоку, на якому запущений код.

Для того, щоб створити потік , нам просто потрібно створити екземпляр класу worker. А потім ми можемо запустити нитку за допомогою функції 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) з класу worker. Тоді ми запускаємо потоки за допомогою функції start () .

Ось остаточний код для створення потоку шляхом розширення класу потоку:

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 потоки не працюють у певній послідовності

Implementing the Runnable Interface

In order to create a piece of code which can be run in a thread, we create a class and then implement the runnable interface. The task being done by this piece of code needs to be put in the run() function.

In the below code you can see that RunnableWorker is a class which implements runnable interface, and the task of printing numbers 0 to 4 is being done inside the run() function.

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

In order to create a thread, first we need to create an Instance of RunnableWorker which implements the runnable interface.

Then we can create a new thread by creating an instance of the thread class and passing the instance of RunnableWorker as the argument. This is shown in the code below:

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(); } } 

The above code creates a runnable instance r. Then it create 3 threads (t1, t2 and t3) and passes r as the argument to the 3 threads. Then the start() function is used to start all 3 threads.

Here is the complete code for creating a thread by implementing the runnable interface:

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(); } } 

On running the above code, we will get the following output. The sequence of the output will change every time the code is run.

Вихідний інтерфейс

Implementing the runnable interface is a better option than extending the thread class since we can extend only one class, but we can implement multiple interfaces in Java.

Runnable Interface in Java 8

In Java 8, the runnable interface becomes a FunctionalInterface since it has only one function, run().

The below code shows how we can create a runnable instance in 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(); } } 

Here, instead of creating a class and then implementing the runnable interface, we can directly use a lambda expression to create a runnable instance as shown below:

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

Code

The code in this article is available in the following GitHub repo: //github.com/aditya-sridhar/basic-threads-demo

Congrats ?

You now know how to create threads by extending the thread class and by implementing the runnable interface.

I will discuss the thread life cycle and challenges while using threads in my next blog post.

My Website: //adityasridhar.com/

Не соромтеся зв’язуватися зі мною в LinkedIn або стежити за мною в Twitter