Home >Java >javaTutorial >Santa's Holiday Race: The Magic of Java Multithreading
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.”
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.
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.
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(); // Уведомляем производителей о свободном месте } } }
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.
“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); } }
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.
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(); // Завершаем работу после выполнения всех задач } }
Asynchronous: tasks are executed in a background thread without blocking the main thread.
Ease of use: no need to manually manage threads.
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! ?
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!