다이아몬드처럼 눈더미가 빛나고 별들이 동화를 속삭이는 머나먼 눈 덮인 왕국에서 산타는 일년 중 가장 마법 같은 밤을 준비하고 있었습니다. 그의 공장은 거대한 악기처럼 윙윙거렸습니다. 엘프들이 상자를 들고 뛰어다니고, 화려한 색상으로 반짝이는 장난감이 있었고, 새로 완성된 선물이 나올 때마다 종소리가 울렸습니다.
하지만 마법이 위협받고 있었습니다.
"장난감이 너무 많아요! 피드가 꽉 찼어요!" — 엘프 수석 프로듀서가 불평했습니다.
"우리는 짐을 꾸릴 시간이 없어요!" - 포장요정이 그에게 반향을 일으켰습니다.
산타는 "엘프들을 어떻게 도울 수 있을까? 그들은 최선을 다하고 있지만 마법 없이는 할 수 없습니다."라고 생각했습니다.
산타는 동기화라는 주문을 사용했습니다. 일반 테이프로 작업할 때 엘프들이 서로 밀치거나 혼동하지 않도록 보호장벽을 만들어 주었습니다.
"이제 한 번에 한 명만 장난감을 내려놓거나 집을 수 있습니다"라고 산타가 설명했습니다.
다음과 같이 생겼습니다.
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 및 informAll의 마법 속성:
wait(): 조건(예: 빈 테이프)이 false가 될 때까지 스레드를 휴면 상태로 둡니다.
informAll(): 대기 중인 모든 스레드를 깨워 계속할 수 있는지 확인합니다.
산타는 엘프들이 종종 informAll 호출을 잊어버리고 이로 인해 지연이 발생한다는 사실을 깨달았습니다. 그런 다음 그는 자체적으로 스레드를 처리하는 마법의 도구인 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): 스레드 중 하나에서 작업을 시작합니다.
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 중국어 웹사이트의 기타 관련 기사를 참조하세요!