首頁 > Java > java教程 > 聖誕老人的節日競賽:Java 多線程的魔力

聖誕老人的節日競賽:Java 多線程的魔力

Patricia Arquette
發布: 2025-01-04 09:04:34
原創
598 人瀏覽過

在遙遠的冰雪王國裡,雪堆像鑽石一樣閃閃發光,星星低語著童話故事,聖誕老人正在為一年中最神奇的夜晚做準備。他的工廠像一架巨大的樂器一樣嗡嗡作響:精靈們拿著盒子跑來跑去,玩具閃閃發光,每一件新的現成禮物都敲響了鈴聲。

但是魔法受到了威脅。

「玩具太多!飼料已滿!」— 精靈首席製作人抱怨道。
「我們沒時間收拾行李!」 - 包裝精靈附和著他。

聖誕老公公想:「我怎麼幫助我的精靈呢?他們已經盡力了,但他們離不開魔法。」

第一個魔法:同步

聖誕老人求助於一種名為「同步」的咒語。它創造了一個保護屏障,讓精靈們在使用普通膠帶時就不會互相推擠和困惑。

「現在一次只有一個人可以放下或拿起玩具,」聖誕老人解釋道。

這就是它的樣子:

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(); // Уведомляем производителей о свободном месте
        }
    }
}

登入後複製
登入後複製

wait和notifyAll的神奇屬性:

wait():使執行緒休眠,直到某個條件(例如空磁帶)變成 false。
notifyAll():喚醒所有等待線程,檢查它們是否可以繼續。

第二個魔法:BlockingQueue

聖誕老人意識到精靈們經常忘記叫notifyAll,這造成了延遲。然後他使用了一個神奇的工具——BlockingQueue,它本身就負責處理線程。

Праздничные гонки Санты: Волшебство многопоточности Java
BlockingQueue 執行以下操作:

如果磁帶已滿,製造商會自動等待。
如果磁帶是空的,打包者自己就會明白他需要等待。

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(); // Уведомляем производителей о свободном месте
        }
    }
}

登入後複製
登入後複製

第三個魔法:執行器和執行緒池

為了讓精靈們不累,聖誕老公公創造了一個神奇的工具-線程池。現在每個精靈各司其職,數量也自動調節。
Праздничные гонки Санты: Волшебство многопоточности Java
「精靈們不會再互相追趕了,一切都很順利。」聖誕老人高興地說。

程式碼範例:

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):建立一個將被重複使用的 n 個執行緒池。
提交(任務):在其中一個執行緒中啟動一項任務。
shutdown():所有任務完成後停止執行。

第四個魔法:CompletableFuture

Праздничные гонки Санты: Волшебство многопоточности Java
在最後階段,聖誕老人添加了一點額外的魔法:現在精靈們非同步工作,這加快了進程。

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(); // Завершаем работу после выполнения всех задач
    }
}

登入後複製

CompletableFuture 的神奇屬性:

非同步:任務在後台執行緒中執行,不會阻塞主執行緒。
易於使用:無需手動管理線程。

新年有救了!

當最後一個玩具裝完後,聖誕老公公高興地嘆了口氣。 「精靈們,你們做了一件了不起的工作。多線程的魔力讓我們不僅更快,而且更快樂!」

現在,在除夕夜的每個晚上,聖誕老人都會向他的助手講述一個關於多線程如何拯救節日的童話故事。

✨ 朋友們,新年快樂! ?

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

以上是聖誕老人的節日競賽:Java 多線程的魔力的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板