Многопоточность в Java: wait и notify
В Java методы wait(), notify(), и notifyAll() используются для управления потоками в многопоточной среде. Они позволяют потокам координировать свои действия при доступе к общим ресурсам, предоставляя механизм для ожидания и уведомления. Эти методы определены в классе Object и должны вызываться из синхронизированного контекста.
Метод wait()
Метод wait() заставляет текущий поток ждать до тех пор, пока другой поток не вызовет метод notify() или notifyAll() для этого объекта. Поток, вызвавший wait(), освобождает монитор и переходит в состояние ожидания.
Пример использования wait():
Метод notify()
Метод notify() пробуждает один из потоков, ожидающих этого объекта. Выбор потока, который будет пробужден, не определяется, поэтому для пробуждения всех ожидающих потоков используется метод notifyAll().
Пример использования notify():
#Java #Training #Multithreading #Medium
В Java методы wait(), notify(), и notifyAll() используются для управления потоками в многопоточной среде. Они позволяют потокам координировать свои действия при доступе к общим ресурсам, предоставляя механизм для ожидания и уведомления. Эти методы определены в классе Object и должны вызываться из синхронизированного контекста.
Метод wait()
Метод wait() заставляет текущий поток ждать до тех пор, пока другой поток не вызовет метод notify() или notifyAll() для этого объекта. Поток, вызвавший wait(), освобождает монитор и переходит в состояние ожидания.
Пример использования wait():
public class WaitNotifyExample {
private final Object lock = new Object();
private boolean condition = false;
public void doWait() {
synchronized (lock) {
while (!condition) {
try {
System.out.println("Waiting...");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Condition met!");
}
}
public void doNotify() {
synchronized (lock) {
condition = true;
lock.notify();
System.out.println("Notified!");
}
}
public static void main(String[] args) {
WaitNotifyExample example = new WaitNotifyExample();
Thread waiter = new Thread(example::doWait);
Thread notifier = new Thread(example::doNotify);
waiter.start();
try {
Thread.sleep(1000); // Задержка для демонстрации ожидания
} catch (InterruptedException e) {
e.printStackTrace();
}
notifier.start();
}
}
Метод notify()
Метод notify() пробуждает один из потоков, ожидающих этого объекта. Выбор потока, который будет пробужден, не определяется, поэтому для пробуждения всех ожидающих потоков используется метод notifyAll().
Пример использования notify():
public class WaitNotifyExample {
private final Object lock = new Object();
private boolean condition = false;
public void doWait() {
synchronized (lock) {
while (!condition) {
try {
System.out.println("Waiting...");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Condition met!");
}
}
public void doNotify() {
synchronized (lock) {
condition = true;
lock.notify();
System.out.println("Notified!");
}
}
public static void main(String[] args) {
WaitNotifyExample example = new WaitNotifyExample();
Thread waiter = new Thread(example::doWait);
Thread notifier = new Thread(example::doNotify);
waiter.start();
try {
Thread.sleep(1000); // Задержка для демонстрации ожидания
} catch (InterruptedException e) {
e.printStackTrace();
}
notifier.start();
}
}
#Java #Training #Multithreading #Medium
Что выведет код?
#Tasks
public class ArrayChallenge {
public static void main(String[] args) {
int[][] array = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int sum = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (i == j || i + j == array.length - 1) {
sum += array[i][j];
}
}
}
System.out.println(sum);
}
}
#Tasks
This media is not supported in your browser
VIEW IN TELEGRAM
Напоминаю!🫡
Скорее всего, если магнитные бури не сотрут нас с лица земли, в воскресение (16:00 МСК) мы продолжим дописывать наше консольное TODO-приложение.
Приходите, будет интересно)😉
Можно будет и просто пообщаться) 🍻
Скорее всего, если магнитные бури не сотрут нас с лица земли, в воскресение (16:00 МСК) мы продолжим дописывать наше консольное TODO-приложение.
Приходите, будет интересно)😉
Продвинутые аспекты wait и notify
Метод notifyAll()
Метод notifyAll() пробуждает все потоки, ожидающие этого объекта. Это полезно в ситуациях, когда несколько потоков могут быть заинтересованы в событии.
Пример использования notifyAll():
Реальный пример: производитель-потребитель
Классическая задача, иллюстрирующая использование wait() и notify(), — это проблема "Производитель-потребитель". В этой задаче один или несколько производителей производят данные и добавляют их в общий буфер, а один или несколько потребителей извлекают данные из буфера.
Метод notifyAll()
Метод notifyAll() пробуждает все потоки, ожидающие этого объекта. Это полезно в ситуациях, когда несколько потоков могут быть заинтересованы в событии.
Пример использования notifyAll():
public class WaitNotifyExample {
private final Object lock = new Object();
private boolean condition = false;
public void doWait() {
synchronized (lock) {
while (!condition) {
try {
System.out.println(Thread.currentThread().getName() + " is waiting...");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " condition met!");
}
}
public void doNotifyAll() {
synchronized (lock) {
condition = true;
lock.notifyAll();
System.out.println("All notified!");
}
}
public static void main(String[] args) {
WaitNotifyExample example = new WaitNotifyExample();
Thread waiter1 = new Thread(example::doWait, "Waiter1");
Thread waiter2 = new Thread(example::doWait, "Waiter2");
Thread notifier = new Thread(example::doNotifyAll);
waiter1.start();
waiter2.start();
try {
Thread.sleep(1000); // Задержка для демонстрации ожидания
} catch (InterruptedException e) {
e.printStackTrace();
}
notifier.start();
}
}
Реальный пример: производитель-потребитель
Классическая задача, иллюстрирующая использование wait() и notify(), — это проблема "Производитель-потребитель". В этой задаче один или несколько производителей производят данные и добавляют их в общий буфер, а один или несколько потребителей извлекают данные из буфера.
import java.util.LinkedList;
import java.util.Queue;
class Buffer {
private final Queue<Integer> queue = new LinkedList<>();
private final int maxSize;
private final Object lock = new Object();
public Buffer(int maxSize) {
this.maxSize = maxSize;
}
public void produce(int value) throws InterruptedException {
synchronized (lock) {
while (queue.size() == maxSize) {
System.out.println("Buffer is full. Producer is waiting...");
lock.wait();
}
queue.add(value);
System.out.println("Produced: " + value);
lock.notifyAll();
}
}
public void consume() throws InterruptedException {
synchronized (lock) {
while (queue.isEmpty()) {
System.out.println("Buffer is empty. Consumer is waiting...");
lock.wait();
}
int value = queue.poll();
System.out.println("Consumed: " + value);
lock.notifyAll();
}
}
}
public class ProducerConsumerExample {
public static void main(String[] args) {
Buffer buffer = new Buffer(5);
Thread producer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
buffer.produce(i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread consumer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
buffer.consume();
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
producer.start();
consumer.start();
}
}
#Java #Training #Multithreading #Medium
Всем доброго солнечного утра!
Хотелось бы чтобы каждый подписчик ответил, что именно из контента ему больше нравится, а что не совсем)) Не стесняйтесь, сделаем канал лучше вместе! Итак что Вам нравится и чего надо побольше?
Хотелось бы чтобы каждый подписчик ответил, что именно из контента ему больше нравится, а что не совсем)) Не стесняйтесь, сделаем канал лучше вместе! Итак что Вам нравится и чего надо побольше?
Anonymous Poll
54%
Обучающих постов
0%
Мемов)))
38%
Задач
0%
Видео гайдов
0%
Онлайн встреч
0%
Всего более чем достаточно, можно и поменьше)))
8%
Я напишу свой вариант в комментариях!
This media is not supported in your browser
VIEW IN TELEGRAM
Запись нашей сегодняшней встречи -
https://www.youtube.com/watch?v=qNwDkOGJ96Q
Спасибо всем кто участвовал👍, продолжение на следующей неделе)))
https://www.youtube.com/watch?v=qNwDkOGJ96Q
Спасибо всем кто участвовал👍, продолжение на следующей неделе)))
Асинхронизм и Future в Java
Асинхронное программирование позволяет выполнять задачи в фоновом режиме, освобождая основной поток для выполнения других операций. Это особенно полезно для задач ввода-вывода, длительных вычислений и работы с внешними сервисами.
Асинхронное выполнение с использованием Future
Интерфейс Future из пакета java.util.concurrent представляет собой результат асинхронной операции. С помощью Future можно проверить, завершилась ли задача, дождаться ее завершения и получить результат.
Пример использования Future и ExecutorService:
Методы интерфейса Future
boolean cancel(boolean mayInterruptIfRunning): Пытается отменить выполнение задачи.
boolean isCancelled(): Возвращает true, если задача была отменена.
boolean isDone(): Возвращает true, если задача завершена.
V get(): Блокирует до завершения задачи и возвращает результат.
V get(long timeout, TimeUnit unit): Блокирует до завершения задачи или до истечения тайм-аута.
Пример использования методов Future:
#Java #Training #Multithreading #Medium
Асинхронное программирование позволяет выполнять задачи в фоновом режиме, освобождая основной поток для выполнения других операций. Это особенно полезно для задач ввода-вывода, длительных вычислений и работы с внешними сервисами.
Асинхронное выполнение с использованием Future
Интерфейс Future из пакета java.util.concurrent представляет собой результат асинхронной операции. С помощью Future можно проверить, завершилась ли задача, дождаться ее завершения и получить результат.
Пример использования Future и ExecutorService:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class FutureExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Callable<Integer> task = () -> {
Thread.sleep(2000);
return 42;
};
Future<Integer> future = executorService.submit(task);
// Выполняем другие задачи
System.out.println("Doing something else while the task is running...");
try {
// Блокируемся до завершения задачи и получаем результат
Integer result = future.get();
System.out.println("Task completed with result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}
}
Методы интерфейса Future
boolean cancel(boolean mayInterruptIfRunning): Пытается отменить выполнение задачи.
boolean isCancelled(): Возвращает true, если задача была отменена.
boolean isDone(): Возвращает true, если задача завершена.
V get(): Блокирует до завершения задачи и возвращает результат.
V get(long timeout, TimeUnit unit): Блокирует до завершения задачи или до истечения тайм-аута.
Пример использования методов Future:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class FutureMethodsExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Callable<Integer> task = () -> {
Thread.sleep(3000);
return 42;
};
Future<Integer> future = executorService.submit(task);
try {
// Проверяем, завершена ли задача
if (!future.isDone()) {
System.out.println("Task is not completed yet...");
}
// Пытаемся получить результат с тайм-аутом
Integer result = future.get(2, TimeUnit.SECONDS);
System.out.println("Task completed with result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (java.util.concurrent.TimeoutException e) {
System.out.println("Task timed out.");
} finally {
future.cancel(true); // Отменяем задачу, если она еще не завершена
executorService.shutdown();
}
}
}
#Java #Training #Multithreading #Medium
Что выведет код?
#Tasks
public class ArrayExample {
public static void main(String[] args) {
int[] array = new int[]{1, 2, 3, 4, 5};
int sum = 0;
for (int i = 0; i < array.length; i++) {
if (i % 2 == 0) {
sum += array[i];
} else {
sum -= array[i];
}
}
System.out.println(sum);
}
}
#Tasks
CompletableFuture в Java
CompletableFuture — это расширение Future, которое предоставляет мощные средства для работы с асинхронными задачами. Он позволяет легко комбинировать и связывать асинхронные операции, использовать методы обратного вызова (callback) и работать с исключениями.
Создание и выполнение задач с помощью CompletableFuture
Методы thenApply, thenAccept и thenRun
thenApply(Function): Применяет функцию к результату завершенного CompletableFuture и возвращает новый CompletableFuture.
thenAccept(Consumer): Принимает потребителя для обработки результата завершенного CompletableFuture.
thenRun(Runnable): Выполняет действие после завершения CompletableFuture, не используя его результат.
Пример использования:
Обработка исключений
CompletableFuture предоставляет методы для обработки исключений, такие как exceptionally, handle и whenComplete.
Пример обработки исключений:
#Java #Training #Multithreading #Medium
CompletableFuture — это расширение Future, которое предоставляет мощные средства для работы с асинхронными задачами. Он позволяет легко комбинировать и связывать асинхронные операции, использовать методы обратного вызова (callback) и работать с исключениями.
Создание и выполнение задач с помощью CompletableFuture
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 42;
});
System.out.println("Doing something else while the task is running...");
try {
Integer result = future.get();
System.out.println("Task completed with result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
Методы thenApply, thenAccept и thenRun
thenApply(Function): Применяет функцию к результату завершенного CompletableFuture и возвращает новый CompletableFuture.
thenAccept(Consumer): Принимает потребителя для обработки результата завершенного CompletableFuture.
thenRun(Runnable): Выполняет действие после завершения CompletableFuture, не используя его результат.
Пример использования:
import java.util.concurrent.CompletableFuture;
public class CompletableFutureChainingExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 42;
}).thenApply(result -> result * 2)
.thenAccept(result -> System.out.println("Result: " + result))
.thenRun(() -> System.out.println("Task completed!"));
}
}
Обработка исключений
CompletableFuture предоставляет методы для обработки исключений, такие как exceptionally, handle и whenComplete.
Пример обработки исключений:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExceptionHandlingExample {
public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (true) {
throw new RuntimeException("Something went wrong!");
}
return 42;
}).exceptionally(ex -> {
System.out.println("Exception: " + ex.getMessage());
return -1;
});
try {
Integer result = future.get();
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
#Java #Training #Multithreading #Medium
Комбинирование CompletableFuture
Методы thenCombine и thenCompose позволяют комбинировать несколько CompletableFuture.
Пример использования thenCombine:
Пример использования thenCompose:
#Java #Training #Multithreading #Medium
Методы thenCombine и thenCompose позволяют комбинировать несколько CompletableFuture.
Пример использования thenCombine:
import java.util.concurrent.CompletableFuture;
public class CompletableFutureCombineExample {
public static void main(String[] args) {
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 42;
});
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 24;
});
CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + result2);
try {
System.out.println("Combined result: " + combinedFuture.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
Пример использования thenCompose:
import java.util.concurrent.CompletableFuture;
public class CompletableFutureComposeExample {
public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 42;
});
CompletableFuture<Integer> composedFuture = future.thenCompose(result ->
CompletableFuture.supplyAsync(() -> result * 2)
);
try {
System.out.println("Composed result: " + composedFuture.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
#Java #Training #Multithreading #Medium
Многопоточность в Java: volatile и Immutable Classes
Volatile
Ключевое слово volatile в Java используется для обозначения переменных, которые могут быть изменены различными потоками. Переменная, объявленная как volatile, гарантирует, что все потоки будут читать ее актуальное значение из основной памяти, а не из кэша процессора. Это помогает избежать некоторых проблем с видимостью, которые могут возникнуть в многопоточных приложениях.
Пример использования volatile
В этом примере поток проверяет значение переменной running и останавливается, когда она становится false. Использование volatile гарантирует, что изменения переменной running будут видны всем потокам.
Immutable Classes
Иммутабельные (неизменяемые) классы — это классы, состояния объектов которых не могут быть изменены после создания. Они особенно полезны в многопоточной среде, так как обеспечивают безопасность потоков (thread-safety) без необходимости использования синхронизации.
Пример неизменяемого класса
В этом примере класс ImmutablePerson является неизменяемым, потому что все его поля final, и они инициализируются только один раз в конструкторе.
Преимущества неизменяемых классов
Потокобезопасность: Нет необходимости в синхронизации, так как состояние объекта не может быть изменено после создания.
Простота использования: Меньше ошибок, связанных с изменением состояния.
Упрощенная разработка: Легче проектировать и отлаживать.
#Java #Training #Multithreading #Medium #Volatile #Immutable_Classes
Volatile
Ключевое слово volatile в Java используется для обозначения переменных, которые могут быть изменены различными потоками. Переменная, объявленная как volatile, гарантирует, что все потоки будут читать ее актуальное значение из основной памяти, а не из кэша процессора. Это помогает избежать некоторых проблем с видимостью, которые могут возникнуть в многопоточных приложениях.
Пример использования volatile
public class VolatileExample {
private volatile boolean running = true;
public void start() {
new Thread(() -> {
while (running) {
System.out.println("Thread is running...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread stopped.");
}).start();
}
public void stop() {
running = false;
}
public static void main(String[] args) {
VolatileExample example = new VolatileExample();
example.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
example.stop();
}
}
В этом примере поток проверяет значение переменной running и останавливается, когда она становится false. Использование volatile гарантирует, что изменения переменной running будут видны всем потокам.
Immutable Classes
Иммутабельные (неизменяемые) классы — это классы, состояния объектов которых не могут быть изменены после создания. Они особенно полезны в многопоточной среде, так как обеспечивают безопасность потоков (thread-safety) без необходимости использования синхронизации.
Пример неизменяемого класса
public final class ImmutablePerson {
private final String name;
private final int age;
public ImmutablePerson(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "ImmutablePerson{name='" + name + "', age=" + age + "}";
}
public static void main(String[] args) {
ImmutablePerson person = new ImmutablePerson("John", 30);
System.out.println(person);
// person.setName("Doe"); // This would cause a compile error
}
}
В этом примере класс ImmutablePerson является неизменяемым, потому что все его поля final, и они инициализируются только один раз в конструкторе.
Преимущества неизменяемых классов
Потокобезопасность: Нет необходимости в синхронизации, так как состояние объекта не может быть изменено после создания.
Простота использования: Меньше ошибок, связанных с изменением состояния.
Упрощенная разработка: Легче проектировать и отлаживать.
#Java #Training #Multithreading #Medium #Volatile #Immutable_Classes
Что выведет код?
#Tasks
public class VariableChallenge {
public static void main(String[] args) {
int x = 5;
final int y;
if (x > 3) {
y = 10;
} else {
y = 20;
}
x = x + y;
int z = x > 15 ? x * 2 : x / 2;
System.out.println(z);
}
}
#Tasks