Producer/Consumer threads using a Queue

前端 未结 7 1773
抹茶落季
抹茶落季 2020-11-22 17:00

I\'d like to create some sort of Producer/Consumer threading app. But I\'m not sure what the best way to implement a queue between the two.

So I\'ve so

7条回答
  •  旧巷少年郎
    2020-11-22 17:38

    Use this typesafe pattern with poison pills:

    public sealed interface BaseMessage {
    
        final class ValidMessage implements BaseMessage {
    
            @Nonnull
            private final T value;
    
    
            public ValidMessage(@Nonnull T value) {
                this.value = value;
            }
    
            @Nonnull
            public T getValue() {
                return value;
            }
    
            @Override
            public boolean equals(Object o) {
                if (this == o) return true;
                if (o == null || getClass() != o.getClass()) return false;
                ValidMessage that = (ValidMessage) o;
                return value.equals(that.value);
            }
    
            @Override
            public int hashCode() {
                return Objects.hash(value);
            }
    
            @Override
            public String toString() {
                return "ValidMessage{value=%s}".formatted(value);
            }
        }
    
        final class PoisonedMessage implements BaseMessage {
    
            public static final PoisonedMessage INSTANCE = new PoisonedMessage();
    
    
            private PoisonedMessage() {
            }
    
            @Override
            public String toString() {
                return "PoisonedMessage{}";
            }
        }
    }
    
    public class Producer implements Callable {
    
        @Nonnull
        private final BlockingQueue messages;
    
        Producer(@Nonnull BlockingQueue messages) {
            this.messages = messages;
        }
    
        @Override
        public Void call() throws Exception {
            messages.put(new BaseMessage.ValidMessage<>(1));
            messages.put(new BaseMessage.ValidMessage<>(2));
            messages.put(new BaseMessage.ValidMessage<>(3));
            messages.put(BaseMessage.PoisonedMessage.INSTANCE);
            return null;
        }
    }
    
    public class Consumer implements Callable {
    
        @Nonnull
        private final BlockingQueue messages;
    
        private final int maxPoisons;
    
    
        public Consumer(@Nonnull BlockingQueue messages, int maxPoisons) {
            this.messages = messages;
            this.maxPoisons = maxPoisons;
        }
    
        @Override
        public Void call() throws Exception {
            int poisonsReceived = 0;
            while (poisonsReceived < maxPoisons && !Thread.currentThread().isInterrupted()) {
                BaseMessage message = messages.take();
                if (message instanceof BaseMessage.ValidMessage vm) {
                    Integer value = (Integer) vm.getValue();
                    System.out.println(value);
                } else if (message instanceof BaseMessage.PoisonedMessage) {
                    ++poisonsReceived;
                } else {
                    throw new IllegalArgumentException("Invalid BaseMessage type: " + message);
                }
            }
            return null;
        }
    }
    

提交回复
热议问题