// 1. Создаём класс, наследующийся от Thread
class MyWorker extends Thread {
@Override
public void run() {
// 2. Переопределяем метод run() с нашей логикой
System.out.println("Поток " + getName() + " начал работу.");
try {
Thread.sleep(2000); // Имитация работы
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Поток " + getName() + " завершил работу.");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyWorker worker1 = new MyWorker();
MyWorker worker2 = new MyWorker();
// 3. Запускаем потоки с помощью метода start()
worker1.start(); // ← Не run(), а именно start()!
worker2.start();
}
}
// 1. Создаём класс, реализующий интерфейс Runnable
class MyTask implements Runnable {
@Override
public void run() {
// 2. Описываем логику задачи
System.out.println("Задача выполняется в потоке: " + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Задача завершена.");
}
}
public class RunnableExample {
public static void main(String[] args) {
MyTask task = new MyTask(); // Создаём задачу (рецепт)
// 3. Создаём потоки и передаём им нашу задачу
Thread thread1 = new Thread(task, "Поток-Алиса"); // ← Можно дать имя потоку
Thread thread2 = new Thread(task, "Поток-Боб");
// 4. Запускаем потоки
thread1.start();
thread2.start();
}
} import java.util.concurrent.*;
class MyCallableTask implements Callable<String> {
@Override
public String call() throws Exception { // ← Возвращает String и может бросить Exception
System.out.println("Callable задача выполняется в потоке: " + Thread.currentThread().getName());
Thread.sleep(3000);
return "Результат выполнения задачи"; // ← Возвращаем результат
}
}
public class CallableExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallableTask task = new MyCallableTask();
// Для работы с Callable нужен ExecutorService
ExecutorService executor = Executors.newSingleThreadExecutor();
// submit() возвращает объект Future, который будет содержать результат в будущем
Future<String> future = executor.submit(task); // ← Отправляем задачу на выполнение
System.out.println("Задача отправлена. Ждём результат...");
// Метод get() блокирует выполнение до получения результата
String result = future.get(); // ← Блокирующий вызов
System.out.println("Результат получен: " + result);
executor.shutdown(); // ← Не забываем关闭ть ExecutorService
}
} start()
┌───────────┐
│ NEW │
└─────┬─────┘
│
▼
┌───────────┐ Выполнение завершено
│ RUNNABLE │ ───────────────────────► TERMINATED
└────┬──────┘
│
┌──────┴───────┐
▼ ▼
┌────────┐ ┌─────────────┐
│BLOCKED │ │ WAITING/ │
└────┬───┘ │TIMED_WAITING│
│ └──────┬──────┘
│ │
└───────┬──────┘
▼
┌───────────┐
│ RUNNABLE │
└───────────┘ Thread t = new Thread(() -> { /* ... */ });
t.start();
t.join(); // ← Основной поток остановится здесь и будет ждать, пока 't' не завершится
System.out.println("Поток 't' завершился, продолжаем работу."); Thread sleeper = new Thread(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("Меня разбудили! Нужно завершаться.");
return; // Корректно завершаем работу
}
});
sleeper.start();
// ...
sleeper.interrupt(); // ← Посылаем сигнал прерывания
}
}