Java for Beginner
672 subscribers
541 photos
155 videos
12 files
827 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Варианты ответа:
Anonymous Quiz
9%
15
18%
20
55%
25
18%
30
Ты 🫵 знаешь что делать!🤪

https://t.me/Java_for_beginner_dev

#Mems
This media is not supported in your browser
VIEW IN TELEGRAM
Напоминаю!🫡

Скорее всего, если магнитные бури не сотрут нас с лица земли, в воскресение (16:00 МСК) мы продолжим дописывать наше консольное TODO-приложение.

Приходите, будет интересно)😉

Можно будет и просто пообщаться) 🍻
Продвинутые аспекты 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%
Я напишу свой вариант в комментариях!
Мы научим Вас производить впечатление на HR😂😎

https://t.me/Java_for_beginner_dev

#Mems
Напоминаю!

Сегодня в 16:00 по МСК, мы вновь соберемся онлайн и продолжим дописывать наше консольное TODO-приложение.

Приходите, будет интересно)😉
This media is not supported in your browser
VIEW IN TELEGRAM
Запись нашей сегодняшней встречи -
https://www.youtube.com/watch?v=qNwDkOGJ96Q

Спасибо всем кто участвовал👍, продолжение на следующей неделе)))
Асинхронизм и Future в Java

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

Асинхронное выполнение с использованием 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
Что выведет код?

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
Варианты ответа:
Anonymous Quiz
10%
4
0%
5
10%
-2
80%
3
Мы все когда-то начинали с Basic😂

https://t.me/Java_for_beginner_dev

#Mems
CompletableFuture в Java

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:

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
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
Что выведет код?

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
Варианты ответа:
Anonymous Quiz
10%
30
0%
25
20%
15
70%
7
Долбанные разработчики 😂

https://t.me/Java_for_beginner_dev

#Mems
Многопоточность в Java: Deadlock

Deadlock (взаимная блокировка) — это состояние, при котором два или более потоков блокируют друг друга, ожидая освобождения ресурсов, занятых друг другом. Это приводит к тому, что ни один из потоков не может продолжать выполнение.
public class DeadlockExample {

private final Object lock1 = new Object();
private final Object lock2 = new Object();

public void method1() {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}

public void method2() {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock 2...");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock1) {
System.out.println("Thread 2: Holding lock 2 & 1...");
}
}
}

public static void main(String[] args) {
DeadlockExample example = new DeadlockExample();

Thread thread1 = new Thread(example::method1);
Thread thread2 = new Thread(example::method2);

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

В этом примере возникает deadlock, потому что thread1 захватывает lock1 и ждет lock2, в то время как thread2 захватывает lock2 и ждет lock1. Таким образом, оба потока оказываются в состоянии взаимной блокировки.

Способы предотвращения Deadlock

Иерархия блокировок: Всегда захватывайте ресурсы в определенном порядке.
Тайм-ауты: Используйте методы с тайм-аутами для захвата блокировок, такие как tryLock из ReentrantLock.
Избегайте вложенных блокировок: Старайтесь минимизировать количество вложенных блокировок.


Пример с использованием tryLock
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;

public class DeadlockAvoidanceExample {

private final Lock lock1 = new ReentrantLock();
private final Lock lock2 = new ReentrantLock();

public void method1() {
try {
if (lock1.tryLock(50, TimeUnit.MILLISECONDS)) {
try {
System.out.println("Thread 1: Holding lock 1...");
Thread.sleep(50);
if (lock2.tryLock(50, TimeUnit.MILLISECONDS)) {
try {
System.out.println("Thread 1: Holding lock 1 & 2...");
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public void method2() {
try {
if (lock2.tryLock(50, TimeUnit.MILLISECONDS)) {
try {
System.out.println("Thread 2: Holding lock 2...");
Thread.sleep(50);
if (lock1.tryLock(50, TimeUnit.MILLISECONDS)) {
try {
System.out.println("Thread 2: Holding lock 2 & 1...");
} finally {
lock1.unlock();
}
}
} finally {
lock2.unlock();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
DeadlockAvoidanceExample example = new DeadlockAvoidanceExample();

Thread thread1 = new Thread(example::method1);
Thread thread2 = new Thread(example::method2);

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

В этом примере tryLock используется для попытки захвата блокировок с тайм-аутом, что предотвращает возникновение deadlock.

#Java #Training #Multithreading #Medium #Deadlock