简体   繁体   中英

spring boot and Executor Service

I am using spring boot

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());
        }

    }

}

}

Class

@Component
public class Test {

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

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

}

In StringConsumeImpl , do I need synchronized while loop? and suppose five time StringConsumeImpl class called, then do while loop will create 5 process or only 1 process ? and what is the best replacement of while loop in StringConsumeImpl , if any ?

There are some problems with that code.

First of all, the consumer doesn't really "consume" anything, it just adds the string to the queue then takes it back out. Let's say for the sake of the argument that it also "consumes" it by printing it to console or something.

Secondly, the consumer will only get called once due to the loop unless it is running in a thread of its own. Eg if you do

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

The consumer will put "hello" into the queue, take it out immediately and then stay in the loop, waiting for more elements to take out; however, no one is there to actually add any.

The usual concept of doing what it looks like you're trying to do is "producer/consumer". This means that there is a "producer" that puts items into a queue and a "consumer" taking them out and doing stuff with them.

So in your case what your class does is "consume" the string by putting it into the queue, making it a "producer", then "consuming" the string by taking it back out of the queue. Of course, there's also the "actual" producer of the string, ie the class calling this.

So in general you'd do something like this:

/** 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");
}

So when you run this, there will be three threads: the main thread, the producer thread and the consumer thread. The producer and consumer will be doing their thing concurrently, and the main thread will also continue to run (as exemplified by the System.out.println in the last line).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM