spring boot和Executor Service

时间:2018-03-14 18:15:09

标签: java spring-boot while-loop executorservice

我正在使用春季靴子

public interface StringConsume extends Consumer<String> {

default public void strHandel(String str) {
    accept(str);
}
}

默认地将Impl

@Component("StrImpl")
public class StringConsumeImpl implements StringConsume {

BlockingQueue<String> queue = new ArrayBlockingQueue<>(500);
final ExecutorService exService = Executors.newSingleThreadExecutor();
Future<?> future = CompletableFuture.completedFuture(true);

@Override
public void accept(String t) {
    try {
        queue.put(t);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    while (null != queue.peek()) {

        if (future.isDone()) {
            future = exService.submit(() -> queue.take());
        }

    }

}

}

@Component
public class Test {

@Resource(name="StrImpl")
private @Autowired StringConsume handler;

public void insertIntoQueue(String str) {
    handler.accept(str);
}

}

在StringConsumeImpl中,我是否需要同步while循环?并假设五次调用StringConsumeImpl类,那么while循环会创建5个进程还是只有1个进程?什么是StringConsumeImpl中while循环的最佳替换,如果有的话?

1 个答案:

答案 0 :(得分:1)

该代码存在一些问题。

首先,消费者并没有真正消费&#34;什么,它只是将字符串添加到队列然后将其取回。让我们为了论证而说它也消费了#34;通过将其打印到控制台或其他东西。

其次,消费者只会因为循环而被调用一次,除非它在自己的线程中运行。例如,如果你这样做

public static void main(String[]args) {
    StringConsume consumer = new StringConsumeImpl();
    consumer.accept("hello");
}

消费者会把&#34;你好&#34;进入队列,立即取出然后留在循环中,等待更多元素取出;但是,没有人可以实际添加任何内容。

做你看起来像你正在做的事情的通常概念是&#34;生产者/消费者&#34;。这意味着有一个&#34;生产者&#34;将物品放入队列和消费者&#34;把它们拿走并用它们做些什么。

因此,在您的情况下,您的课程所做的是&#34;消费&#34;将字符串放入队列,使其成为&#34;生产者&#34;然后&#34;消费&#34;通过将其从队列中取回来的字符串。当然,还有&#34;实际&#34;字符串的生成者,即调用它的类。

所以一般来说你做这样的事情:

/** Produces random Strings */
class RandomStringProducer {
    Random random = new Random();
    public String produceString() {
        return Double.toString(random.nextDouble());
    }
}

/** Prints a String */
class PrintConsumer implements StringConsume {
    public void accept(String s) { System.out.println(s); }
}

/** Consumes String by putting it into a queue */
class QueueProducer implements StringConsume {
    BlockingQueue<String> queue;
    public QueueProducer(BlockingQueue<String> q) { queue = q; }
    public void accept(String s) {
        queue.put(s);
    }
}

public static void main(String[] args) {
    // the producer
    RandomStringProducer producer = new RandomStringProducer();

    // the end consumer
    StringConsume printConsumer = new PrintConsumer();

    // the queue that links producer and consumer
    BlockingQueue<String> queue = new ArrayBlockingQueue<>();

    // the consumer putting strings into the queue
    QueueProducer queuePutter = new QueueProducer(queue);

    // now, let's tie them together

    // one thread to produce strings and put them into the queue
    ScheduledExecutorService producerService = Executors.newScheduledThreadPool(1);
    Runnable createStringAndPutIntoQueue = () -> {
        String created = producer.createString();
        queuePutter.consume(created);
    };
    // put string into queue every 100ms
    producerService.scheduleAtFixedRate(createStringAndPutIntoQueue, 100, TimeUnit.MILLISECONDS);

    // one thread to consume strings
    Runnable takeStringFromQueueAndPrint = () -> {
        while(true) {
            String takenFromQueue = queue.take(); // this will block until a string is available
            printConsumer.consume(takenFromQueue);
        }
    };
    // let it run in a different thread
    ExecutorService consumerService = Executors.newSingleThreadExecutor();
    consumerService.submit(takeStringFromQueueAndPrint);

    // this will be printed; we are in the main thread and code is still being executed
    System.out.println("the produce/consume has started");
}

所以当你运行它时,会有三个线程:主线程,生产者线程和消费者线程。生产者和消费者将同时做他们的事情,主线程也将继续运行(如最后一行中的System.out.println所示)。