All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wowtools.common.pcm.ltp.LtpPcmTask Maven / Gradle / Ivy

The newest version!
package org.wowtools.common.pcm.ltp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wowtools.common.pcm.Customer;
import org.wowtools.common.utils.AsyncTaskUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 构造一个生产者-消费者队列任务,生产者生产的数据是有限的,生产者、消费者可以是一对一、一对多、多对多、多对一的
 *
 * @author liuyu
 * @date 2016年12月6日
 */
public class LtpPcmTask {
    private static final Logger log = LoggerFactory.getLogger(LtpPcmTask.class);
    private final Collection> producers;
    private final Collection> customers;
    private final LtpBufferPool bufferPool;
    private final AtomicBoolean allFinish = new AtomicBoolean(false);
    private final long waitMilliSecones;

    /**
     * 构造一个指定容量缓冲池的任务,试图向已满队列中放入元素会导致操作受阻塞
     *
     * @param producers        生产者
     * @param customers        消费者
     * @param capacity         缓冲池最大限制
     * @param waitMilliSecones 消费者等待生产者毫秒数,等待超时后重试,直至生产者宣告生产结束
     */
    public LtpPcmTask(Collection> producers, Collection> customers, int capacity, long waitMilliSecones) {
        this.producers = producers;
        this.customers = customers;
        this.bufferPool = new LtpBufferPool<>(capacity, waitMilliSecones);
        this.waitMilliSecones = waitMilliSecones;
    }

    /**
     * 构造一个指定容量缓冲池的任务,试图向已满队列中放入元素会导致操作受阻塞
     *
     * @param producer         生产者
     * @param customers        消费者
     * @param capacity         缓冲池最大限制
     * @param waitMilliSecones 消费者等待生产者毫秒数,等待超时后重试,直至生产者宣告生产结束
     */
    public LtpPcmTask(LtpProducer producer, Collection> customers, int capacity, long waitMilliSecones) {
        producers = new ArrayList<>(1);
        producers.add(producer);
        this.customers = customers;
        this.bufferPool = new LtpBufferPool<>(capacity, waitMilliSecones);
        this.waitMilliSecones = waitMilliSecones;
    }

    /**
     * 构造一个指定容量缓冲池的任务,试图向已满队列中放入元素会导致操作受阻塞
     *
     * @param producers        生产者
     * @param customer         消费者
     * @param capacity         缓冲池最大限制
     * @param waitMilliSecones 消费者等待生产者毫秒数,等待超时后重试,直至生产者宣告生产结束
     */
    public LtpPcmTask(Collection> producers, Customer customer, int capacity, long waitMilliSecones) {
        this.producers = producers;
        customers = new ArrayList<>(1);
        customers.add(customer);
        this.bufferPool = new LtpBufferPool<>(capacity, waitMilliSecones);
        this.waitMilliSecones = waitMilliSecones;
    }

    /**
     * 构造一个指定容量缓冲池的任务,试图向已满队列中放入元素会导致操作受阻塞
     *
     * @param producer         生产者
     * @param customer         消费者
     * @param capacity         缓冲池最大限制
     * @param waitMilliSecones 消费者等待生产者毫秒数,等待超时后重试,直至生产者宣告生产结束
     */
    public LtpPcmTask(LtpProducer producer, Customer customer, int capacity, long waitMilliSecones) {
        producers = new ArrayList<>(1);
        producers.add(producer);
        customers = new ArrayList<>(1);
        customers.add(customer);
        this.bufferPool = new LtpBufferPool<>(capacity, waitMilliSecones);
        this.waitMilliSecones = waitMilliSecones;
    }

    private static class ExceptionCell {
        Object o;
    }

    /**
     * 开始任务
     *
     * @param wait 是否等待任务结束(生产者生产完成,消费者消费完成)
     */
    public void startTask(boolean wait) {
        ExceptionCell exceptionCell = new ExceptionCell();
        //启动生产者
        for (LtpProducer producer : producers) {
            AsyncTaskUtil.execute(() -> {
                try {
                    while (!producer.isFinish() && exceptionCell.o == null) {
                        T obj = producer.produce();
                        if (null == obj) {
                            break;
                        }
                        bufferPool.add(obj);
                    }
                } catch (Exception e) {
                    log.warn("生产者执行异常", e);
                    exceptionCell.o = producer;
                }
            });
        }
        //启动消费者
        final Semaphore semp = new Semaphore(0);
        for (Customer customer : customers) {
            AsyncTaskUtil.execute(() -> {
                try {
                    while (true) {
                        T obj = bufferPool.take();
                        if (null != obj) {
                            customer.consume(obj);
                        } else {
                            //检查是否有异常发生
                            if (exceptionCell.o == null) {
                                //若缓冲池为空,检查是否所有生产者都已生产完成
                                if (isAllFinish()) {
                                    break;//为空则结束
                                }
                            } else {
                                //异常的话直接结束
                                bufferPool.clear();//尽量防止生产者阻塞
                                break;
                            }

                        }
                    }
                } catch (Exception e) {
                    log.warn("消费者执行异常", e);
                    exceptionCell.o = customer;
                }
                semp.release();
            });
        }
        if (wait) {
            boolean finish;
            do {
                try {
                    finish = semp.tryAcquire(customers.size(), waitMilliSecones, TimeUnit.MILLISECONDS);
                    if (!finish && exceptionCell.o != null) {
                        log.warn(exceptionCell.o.getClass() + "执行异常,退出");
                        break;
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            } while (!finish);
        }

    }

    private boolean isAllFinish() {
        if (allFinish.get()) {
            return true;
        }
        for (LtpProducer producer : producers) {
            if (!producer.isFinish()) {
                return false;
            }
        }
        allFinish.set(true);
        return true;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy