雪の吹きだまりがダイヤモンドのように輝き、星がおとぎ話をささやく遠く離れた雪の王国で、サンタは一年で最も魔法の夜に向けて準備をしていました。彼の工場は巨大な楽器のようにうなり声を上げ、エルフたちは箱を持って走り回り、おもちゃは色とりどりに輝き、新しい既製の贈り物ごとに鐘が鳴り響きました。
しかし、魔法は脅威にさらされていました。
「おもちゃが多すぎる!餌がいっぱいだ!」 — エルフのチーフプロデューサーは不満を漏らした。
「荷物をまとめる時間がない!」 - 梱包するエルフも彼の言葉に同調しました。
サンタさんはこう考えました。「どうすればエルフたちを助けることができるでしょうか?彼らは一生懸命頑張っていますが、魔法なしではやっていけないのです。」
サンタは同期として知られる呪文に目を向けました。エルフたちが共通のテープを扱うときに衝突したり混乱したりしないように、保護バリアを作成しました。
「おもちゃを置いたり拾ったりできるのは、一度に 1 人だけです。」とサンタさんが説明しました。
これは次のようになります:
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 と NoticeAll の魔法のプロパティ:
wait(): 条件 (空のテープなど) が false になるまでスレッドをスリープします。
NoticeAll(): 待機中のすべてのスレッドを起動して、続行できるかどうかを確認します。
サンタさんは、エルフたちがよくnotifyAllを呼び出すのを忘れており、それが遅延を引き起こしていることに気づきました。次に、彼は魔法のツール BlockingQueue を使用しました。BlockingQueue 自体がスレッドを処理します。
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(); // Уведомляем производителей о свободном месте } } }
エルフたちが疲れないようにするために、サンタは魔法の道具、糸のプールを作りました。これで、各エルフは自分のタスクを実行し、その数は自動的に調整されました。
「もうエルフたちはお互いを追いかけることはなくなり、すべてが順調に進んでいます。」サンタは喜びました。
コード例:
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 個のスレッドのプールを作成します。
submit(task): スレッドの 1 つでタスクを開始します。
shutdown(): すべてのタスクが完了した後に実行を停止します。
最後の段階で、サンタは少し魔法を加えました。エルフが非同期で動作するようになり、プロセスが高速化されました。
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(); // Завершаем работу после выполнения всех задач } }
非同期: タスクはメインスレッドをブロックせずにバックグラウンドスレッドで実行されます。
使いやすさ: スレッドを手動で管理する必要はありません。
最後のおもちゃが梱包されると、サンタさんは喜びのため息をつきました。 「エルフの皆さん、素晴らしい仕事をしてくれました。マルチスレッドの魔法のおかげで、私たちは速くなっただけでなく、より幸せになりました!」
そして現在、大晦日の夜、サンタはアシスタントたちに、マルチスレッドがどのように休日を救ったのかについてのおとぎ話を話します。
✨ 明けましておめでとうございます、皆さん! ?
以上がサンタのホリデー レース: Java マルチスレッドの魔法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。