Клас Thread. Створення та виконання потоків

Прокрутити вниз

Клас Thread. Створення та виконання потоків – онлайн курс java

Клас Thread. Створення та виконання потоків у Java

У Java потоки (threads) дозволяють виконувати кілька завдань паралельно, що може підвищити продуктивність програм, особливо на багатоядерних процесорах. Клас Thread використовується для створення і керування потоками.

Основні способи створення потоків

У Java існує два основних способи створення потоків:

1. Наслідування класу Thread.
2. Реалізація інтерфейсу Runnable.

1. Наслідування класу Thread

Цей спосіб передбачає створення класу, який наслідує клас `Thread`, та перевизначення методу **`run()`**. Метод `run()` містить код, який буде виконуватися в окремому потоці.

Приклад:

class MyThread extends Thread {
public void run() {
// Код, який виконується у потоці
for (int i = 1; i <= 5; i++) {
System.out.println(i + ” від потоку ” + Thread.currentThread().getName());
try {
Thread.sleep(500); // Затримка на 500 мілісекунд
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public class Main {
public static void main(String[] args) {
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();

// Запуск потоків
thread1.start();
thread2.start();
}
}

  • Метод start() використовується для запуску нового потоку, який викликає метод run() у фоновому режимі.
  • Thread.sleep() ставить потік у “сон” на вказаний час у мілісекундах.

2. Реалізація інтерфейсу Runnable

Цей спосіб більш гнучкий, оскільки Java не підтримує множинне наслідування, і клас може наслідувати лише один клас. Але клас може реалізувати кілька інтерфейсів, тому реалізація `Runnable` є поширеним способом створення потоків.

Приклад:

class MyRunnable implements Runnable {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(i + ” від потоку ” + Thread.currentThread().getName());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public class Main {
public static void main(String[] args) {
// Створення об’єкта класу MyRunnable
MyRunnable myRunnable = new MyRunnable();

// Створення потоків, які виконуватимуть myRunnable
Thread thread1 = new Thread(myRunnable);
Thread thread2 = new Thread(myRunnable);

// Запуск потоків
thread1.start();
thread2.start();
}
}

Різниця між Thread і Runnable:

  • Використання інтерфейсу Runnable є кращою практикою, оскільки це дозволяє класу реалізовувати інші інтерфейси і дотримуватися принципу композиції.
  • У разі наслідування класу Thread, клас вже не може наслідувати інший клас.

Методи класу Thread

  1. start(): Запускає новий потік, який автоматично викликає метод `run()`.
  2. run(): Вміст цього методу виконується у новому потоці. Ви можете перевизначити його при наслідуванні класу `Thread` або реалізації інтерфейсу `Runnable`.
  3. sleep(long millis): Призупиняє виконання потоку на вказаний час у мілісекундах.
  4. join(): Очікує завершення виконання потоку. thread1.join(); // Очікує, поки thread1 завершить роботу
  5. currentThread(): Повертає поточний потік, що виконується. Thread t = Thread.currentThread();
  6. getName() і setName(): Отримує або задає ім’я потоку. thread1.setName(“FirstThread”); System.out.println(thread1.getName()); // Output: FirstThread
  7. isAlive(): Перевіряє, чи потік ще виконується. if (thread1.isAlive()) { System.out.println(“Thread is still running”);}
  8. interrupt(): Перериває потік.

Демонічні потоки (Daemon Threads)

Демонічні потоки — це фонові потоки, які не блокують завершення програми, навіть якщо вони ще виконуються. Якщо всі не демонічні потоки завершені, JVM завершить роботу, навіть якщо демонічні потоки ще активні.

Щоб зробити потік демонічним, використовується метод setDaemon(true)

Приклад:

Thread daemonThread = new Thread(() -> {
while (true) {
System.out.println(“Демонічний потік виконується…”);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
daemonThread.setDaemon(true);
daemonThread.start();

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

Коли кілька потоків працюють одночасно і взаємодіють з одним і тим самим об’єктом, може виникнути проблема взаємного виключення (race condition). Java надає механізми для синхронізації потоків, щоб уникнути таких ситуацій.

synchronized — ключове слово для блокування доступу до певного ресурсу для кількох потоків одночасно.

Приклад синхронізації:

class Counter {
private int count = 0;

public synchronized void increment() {
count++;
}

public int getCount() {
return count;
}
}

public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();

Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});

Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});

thread1.start();
thread2.start();

thread1.join();
thread2.join();

System.out.println(“Значення лічильника: ” + counter.getCount());
}
}

У цьому прикладі метод `increment()` синхронізований, тому лише один потік одночасно може його виконувати, що запобігає проблемам із некоректною модифікацією змінної `count`.

Висновок:

  • Клас Thread дозволяє створювати і керувати потоками у Java.
  • Існує два основних способи створення потоків: наслідування від класу `Thread` та реалізація інтерфейсу `Runnable`.
  • Потоки дозволяють виконувати кілька завдань одночасно, що може значно покращити продуктивність програм.
  • Для запобігання конфліктам під час роботи з потоками, Java пропонує механізми синхронізації, такі як ключове слово synchronized.

Клас Thread Створення та виконання потоків