Home >Java >javaTutorial >Santa's Holiday Race: The Magic of Java Multithreading

Santa's Holiday Race: The Magic of Java Multithreading

Patricia Arquette
Patricia ArquetteOriginal
2025-01-04 09:04:34604browse

In a distant snowy kingdom, where snowdrifts shine like diamonds and the stars whisper fairy tales, Santa was preparing for the most magical night of the year. His factory hummed like a giant musical instrument: elves were running around with boxes, toys sparkled with colorful colors, and bells rang with each new ready-made gift.

But the magic was under threat.

"Too many toys! The feed is full!" — the chief elf-producer complained.
"We don't have time to pack!" - the packing elf echoed him.

Santa thought: “How can I help my elves? They are trying their best, but they can’t do without magic.”

First Magic: Synchronization

Santa turned to a spell known as synchronized. It created a protective barrier so that the elves would not jostle and get confused when working with the common tape.

"Now only one of you can put down or pick up toys at a time," Santa explained.

This is what it looked like:

class SantaFactory {
    private final Queue<String> conveyorBelt = new LinkedList<>();
    private final int MAX_CAPACITY = 10;

    public void produce(String toy) throws InterruptedException {
        synchronized (conveyorBelt) {
            while (conveyorBelt.size() == MAX_CAPACITY) {
                System.out.println("Производитель ждёт: лента заполнена!");
                conveyorBelt.wait(); // Производитель ждёт, пока появится место
            }
            conveyorBelt.add(toy);
            System.out.println("Игрушка произведена: " + toy);
            conveyorBelt.notifyAll(); // Уведомляем упаковщиков о новой игрушке
        }
    }

    public void consume() throws InterruptedException {
        synchronized (conveyorBelt) {
            while (conveyorBelt.isEmpty()) {
                System.out.println("Потребитель ждёт: игрушек нет!");
                conveyorBelt.wait(); // Упаковщик ждёт, пока появится игрушка
            }
            String toy = conveyorBelt.poll();
            System.out.println("Игрушка упакована: " + toy);
            conveyorBelt.notifyAll(); // Уведомляем производителей о свободном месте
        }
    }
}

Magical properties of wait and notifyAll:

wait(): Sleeps the thread until a condition (such as empty tape) becomes false.
notifyAll(): Wake up all waiting threads to check if they can continue.

Second Magic: BlockingQueue

Santa realized that the elves often forgot to call notifyAll, and this created delays. Then he used a magical tool - BlockingQueue, which itself took care of the threads.

Праздничные гонки Санты: Волшебство многопоточности Java
BlockingQueue does the following:

If the tape is full, the manufacturer automatically waits.
If the tape is empty, the packer himself understands that he needs to wait.

class SantaFactory {
    private final Queue<String> conveyorBelt = new LinkedList<>();
    private final int MAX_CAPACITY = 10;

    public void produce(String toy) throws InterruptedException {
        synchronized (conveyorBelt) {
            while (conveyorBelt.size() == MAX_CAPACITY) {
                System.out.println("Производитель ждёт: лента заполнена!");
                conveyorBelt.wait(); // Производитель ждёт, пока появится место
            }
            conveyorBelt.add(toy);
            System.out.println("Игрушка произведена: " + toy);
            conveyorBelt.notifyAll(); // Уведомляем упаковщиков о новой игрушке
        }
    }

    public void consume() throws InterruptedException {
        synchronized (conveyorBelt) {
            while (conveyorBelt.isEmpty()) {
                System.out.println("Потребитель ждёт: игрушек нет!");
                conveyorBelt.wait(); // Упаковщик ждёт, пока появится игрушка
            }
            String toy = conveyorBelt.poll();
            System.out.println("Игрушка упакована: " + toy);
            conveyorBelt.notifyAll(); // Уведомляем производителей о свободном месте
        }
    }
}

Third Magic: Executors and Thread Pool

To keep the elves from getting tired, Santa created a magical tool - a thread pool. Now each elf performed his task, and their number was automatically regulated.
Праздничные гонки Санты: Волшебство многопоточности Java
“The elves will no longer run after each other, everything is running smoothly,” Santa rejoiced.

Code example:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

class SantaFactoryBlocking {
    private final BlockingQueue<String> conveyorBelt = new ArrayBlockingQueue<>(10);

    public void produce(String toy) throws InterruptedException {
        conveyorBelt.put(toy); // Если лента заполнена, поток автоматически ждёт
        System.out.println("Игрушка произведена: " + toy);
    }

    public void consume() throws InterruptedException {
        String toy = conveyorBelt.take(); // Если лента пуста, поток автоматически ждёт
        System.out.println("Игрушка упакована: " + toy);
    }
}

Magic properties of Executors:

newFixedThreadPool(n): Creates a pool of n threads that will be reused.
submit(task): Starts a task in one of the threads.
shutdown(): Stops execution after all tasks have completed.

Fourth Magic: CompletableFuture

Праздничные гонки Санты: Волшебство многопоточности Java
At the last stage, Santa added a little extra magic: now the elves worked asynchronously, which speeded up the process.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SantaRaceWithExecutors {
    public static void main(String[] args) {
        SantaFactoryBlocking factory = new SantaFactoryBlocking();
        ExecutorService executor = Executors.newFixedThreadPool(4); // 4 эльфа

        // Запускаем 2 производителя
        for (int i = 1; i <= 2; i++) {
            executor.submit(() -> {
                try {
                    for (int j = 1; j <= 20; j++) {
                        factory.produce("Игрушка #" + j);
                        Thread.sleep(100); // Производство занимает время
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        // Запускаем 2 упаковщика
        for (int i = 1; i <= 2; i++) {
            executor.submit(() -> {
                try {
                    for (int j = 1; j <= 20; j++) {
                        factory.consume();
                        Thread.sleep(150); // Упаковка занимает время
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        executor.shutdown(); // Завершаем работу после выполнения всех задач
    }
}

Magic properties of CompletableFuture:

Asynchronous: tasks are executed in a background thread without blocking the main thread.
Ease of use: no need to manually manage threads.

New Year is saved!

When the last toys were packed, Santa sighed with joy. "Elves, you have done an incredible job. The magic of multithreading has made us not only faster, but also happier!"

And now, every night on New Year's Eve, Santa tells his assistants a fairy tale about how multithreading saved the holiday.

✨ Happy New Year, friends! ?

Праздничные гонки Санты: Волшебство многопоточности Java

The above is the detailed content of Santa's Holiday Race: The Magic of Java Multithreading. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn