java多线程设计模式 -- 流水线模式(Pipeline)

十一、流水线模式(Pipeline)
1、核心思想
将一个任务处理分解为若干个处理阶段,其中每个处理阶段的输出作为下一个处理阶段的输入,并且各个处理阶段都有相应的工作者线程去执行相应的计算。
2、评价:
充分利用CPU,提高其计算效率。
允许子任务间存在依赖关系的条件下实现并行计算。
非常便于采用单线程模型实现对子任务的处理。
有错误处理 PipeContext
3、适用场景
a、适合于处理规模较大的任务,否则可能得不偿失。各个处理阶段所使用的工作者线程或者线程池、输入输出对象的创建和转移都有自身的时间和空间消耗。

/**
 * 对处理阶段的抽象。
 * 负责对输入进行处理,并将输出作为下一处理阶段的输入
 * @author huzhiqiang
 *
 * @param <IN>
 * @param <OUT>
 */
public interface Pipe<IN, OUT> {
    /**
     * 设置当前Pipe实例的下个Pipe实例
     * @param nextPipe
     */
    public void setNextPipe(Pipe<?,?> nextPipe);

    /**
     * 对输入的元素进行处理,并将处理结果作为下一个Pipe实例的输入
     * @param input
     * @throws InterruptedException
     */
    public void process(IN input) throws InterruptedException;

    public void init(PipeContext pipeCtx);
    public void shutdown(long timeout, TimeUnit unit);
}


/**
 * 对复合Pipe的抽象。一个Pipeline实例可包含多个Pipe实例
 * @author huzhiqiang
 *
 * @param <IN>
 * @param <OUT>
 */
public interface PipeLine<IN, OUT> extends Pipe<IN, OUT> {
    void addPipe(Pipe<?,?> pipe);
}



public abstract class AbsractPipe<IN, OUT> implements Pipe<IN, OUT> {
    protected volatile Pipe<?, ?> nextPipe = null;
    protected volatile PipeContext PipeCtx = null;

    @Override
    public void setNextPipe(Pipe<?, ?> nextPipe) {
        this.nextPipe = nextPipe;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void process(IN input) throws InterruptedException {
        try {
            OUT out = doProcess(input);
            if(null != nextPipe){
                if(null != out){
                    ((Pipe<OUT, ?>) nextPipe).process(out);
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (PipeException e) {
            PipeCtx.handleError(e);
        }

    }

    @Override
    public void init(PipeContext pipeCtx) {
        this.PipeCtx = pipeCtx;
    }

    @Override
    public void shutdown(long timeout, TimeUnit unit) {
        //什么也不做
    }

    /**
     * 留给子类实现,用于子类实现其任务处理逻辑
     */
    public abstract OUT doProcess(IN input) throws PipeException;
}


public abstract class AbstractParallePipe<IN, OUT, V> extends AbsractPipe<IN, OUT> {
    private final ExecutorService executorService;

    public AbstractParallePipe(BlockingQueue<IN> queue, ExecutorService executorService) {
        super();
        this.executorService = executorService;
    }

    /**
     * 留给子类实现,用于根据指定的输入元素input构造一组子任务
     * @param input
     * @return
     * @throws Exception
     */
    protected abstract List<Callable<V>> buildTasks(IN input) throws Exception;

    /**
     * 留给子类实现,对各个子任务的处理结果进行合并,形成相应输入元素的输出结果
     * @param subTaskResults
     * @return
     * @throws Exception
     */
    protected abstract OUT combineResults(List<Future<V>> subTaskResults) throws Exception;

    /**
     * 以并行的方式执行一组子任务
     * @param tasks
     * @return
     * @throws Exception
     */
    protected List<Future<V>> invokeParallel(List<Callable<V>> tasks) throws Exception{
        return executorService.invokeAll(tasks);
    }


    @Override
    public OUT doProcess(IN input) throws PipeException {
        OUT out = null;
        try {
            out = combineResults(invokeParallel(buildTasks(input)));
        } catch (Exception e) {
            throw new PipeException(this, input, "Task failed", e);
        }
        return out;
    }

}


public class SimplePipeline<IN, OUT> extends AbsractPipe<IN, OUT> implements PipeLine<IN, OUT> {
    private final Queue<Pipe<?, ?>> pipes = new LinkedList<Pipe<?, ?>>();
    private final ExecutorService helperService;

    public SimplePipeline() {
        //创建固定线程数为1的线程池,整型的最大数的LinkedBlockingQueue的缓存队列
        this(Executors.newSingleThreadExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r, "SimplePpeLine-Helper");
                t.setDaemon(true);
                return t;
            }
        }));
    }

    public SimplePipeline(final ExecutorService helperService) {
        super();
        this.helperService = helperService;
    }

    @Override
    public void shutdown(long timeout, TimeUnit unit) {
        Pipe<?,?> pipe;

        while(null != (pipe = pipes.poll())){
            pipe.shutdown(timeout, unit);
        }

        helperService.shutdown();
    }

    @Override
    public void addPipe(Pipe<?, ?> pipe) {
        pipes.add(pipe);
    }

    @Override
    public OUT doProcess(IN input) throws PipeException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void process(IN input) throws InterruptedException {
        @SuppressWarnings("unchecked")
        Pipe<IN, ?> firstPipe = (Pipe<IN, ?>) pipes.peek();

        firstPipe.process(input);
    }

    @Override
    public void init(PipeContext pipeCtx) {
        LinkedList<Pipe<?, ?>> pipesList = (LinkedList<Pipe<?, ?>>) pipes;
        Pipe<?, ?> prevPipe = this;
        //设置处理任务的先后顺序
        for(Pipe<?, ?> pipe: pipesList){
            prevPipe.setNextPipe(pipe);
            prevPipe = pipe;
        }

        Runnable task = new Runnable() {
            @Override
            public void run() {
                for(Pipe<?, ?> pipe: pipes){
                    pipe.init(pipeCtx);
                }
            }
        };

        helperService.submit(task);
    }

    public <INPUT, OUTPUT> void addAsWorkerThreadBasedPipe(Pipe<INPUT, OUTPUT> delegate, int workCount){
        addPipe(new WorkThreadPipeDecorator<INPUT, OUTPUT>(delegate, workCount));
    }

    public <INPUT, OUTPUT> void addAsThreadBasedPipe(Pipe<INPUT, OUTPUT> delegate, ExecutorService executorService){
        addPipe(new ThreadPoolPipeDecorator<INPUT, OUTPUT>(delegate, executorService));
    }

    public PipeContext newDefaultPipeContext(){
        return new PipeContext() {
            @Override
            public void handleError(PipeException exp) {
                helperService.submit(new Runnable() {
                    @Override
                    public void run() {
                        exp.printStackTrace();
                    }
                });
            }
        };
    }
}



public class ThreadPoolPipeDecorator<IN, OUT> implements Pipe<IN, OUT> {
    private final Pipe<IN, OUT> delegate;
    private final TerminationToken terminationToken;
    private final ExecutorService executorService;
    private final CountDownLatch stageProcessDoneLatch = new CountDownLatch(1);

    public ThreadPoolPipeDecorator(Pipe<IN, OUT> delegate, ExecutorService executorService) {
        super();
        this.delegate = delegate;
        this.executorService = executorService;
        terminationToken = TerminationToken.newInstance(executorService);
    }

    @Override
    public void setNextPipe(Pipe<?, ?> nextPipe) {
        delegate.setNextPipe(nextPipe);
    }

    @Override
    public void process(IN input) throws InterruptedException {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                int remainingReservations = -1;
                try {
                    delegate.process(input);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    remainingReservations = terminationToken.reservations.decrementAndGet();
                }

                if(terminationToken.isToShutDown()  &&  0 == remainingReservations){
                    //最后一个任务执行结束
                    stageProcessDoneLatch.countDown();
                }
            }
        };

        executorService.submit(task);
        terminationToken.reservations.incrementAndGet();
    }

    @Override
    public void init(PipeContext pipeCtx) {
        delegate.init(pipeCtx);
    }

    @Override
    public void shutdown(long timeout, TimeUnit unit) {
        terminationToken.setIsToShutdown();
        if(terminationToken.reservations.get() > 0){
            try {
                if(stageProcessDoneLatch.getCount() > 0){
                    //保证线程池中的所有任务都已经执行结束才delegate.shutdown
                    stageProcessDoneLatch.await(timeout, unit);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        delegate.shutdown(timeout, unit);
    }

    private static class TerminationToken extends com.threadDesign.twoPhase.TerminationToken{
        private final static ConcurrentHashMap<ExecutorService, TerminationToken> 
            INSTANCE_MAP = new ConcurrentHashMap<ExecutorService, TerminationToken>();

        private TerminationToken(){

        }

        void setIsToShutdown(){
            this.toShutDown = true;
        }

        static TerminationToken newInstance(ExecutorService executorService){
            TerminationToken token = INSTANCE_MAP.get(executorService);
            if(null == token){
                token = new TerminationToken();
                TerminationToken existingToken = INSTANCE_MAP.putIfAbsent(executorService, token);

                if(null != existingToken){
                    token = existingToken;
                }
            }

            return token;
        }
    }
}


/**
 * 基于工作者线程的Pipe实现类
 * 提交到该Pipe的任务由指定个数的工作者线程共同处理
 * @author huzhiqiang
 *
 * @param <IN>
 * @param <OUT>
 */
public class WorkThreadPipeDecorator<IN, OUT> implements Pipe<IN, OUT> {
    protected final BlockingQueue<IN> workQueue;
    protected final Set<AbstractTerminatableThread> workerThreads = new HashSet<AbstractTerminatableThread>();
    protected final TerminationToken terminationToken = new TerminationToken();

    private final Pipe<IN, OUT> delegate;

    public WorkThreadPipeDecorator(Pipe<IN, OUT> delegate, int workerCount){
        this(new SynchronousQueue<IN>(), delegate, workerCount);
    }

    public WorkThreadPipeDecorator(BlockingQueue<IN> workQueue, Pipe<IN, OUT> delegate, int workerCount) {
        if(workerCount <= 0){
            throw new IllegalArgumentException("workerCount should be positive!");
        }

        this.workQueue = workQueue;
        this.delegate = delegate;
        for(int i=0; i<workerCount; i++){
            workerThreads.add(new AbstractTerminatableThread() {

                @Override
                protected void doRun() throws Exception {
                    try {
                        dispatch();
                    }finally {
                        terminationToken.reservations.decrementAndGet();
                    }
                }
            });
        }
    }

    private void dispatch() throws InterruptedException {
        IN input = workQueue.take();
        delegate.process(input);
    }

    @Override
    public void setNextPipe(Pipe<?, ?> nextPipe) {
        delegate.setNextPipe(nextPipe);
    }

    @Override
    public void process(IN input) throws InterruptedException {
        workQueue.put(input);
        terminationToken.reservations.incrementAndGet();
    }

    @Override
    public void init(PipeContext pipeCtx) {
        delegate.init(pipeCtx);
        for(AbstractTerminatableThread thread : workerThreads){
            thread.start();
        }
    }

    @Override
    public void shutdown(long timeout, TimeUnit unit) {
        for(AbstractTerminatableThread thread : workerThreads){
            thread.terminate();
            try {
                thread.join(TimeUnit.MILLISECONDS.convert(timeout, unit));
            } catch (InterruptedException e) {
            }
        }
        delegate.shutdown(timeout, unit);
    }

}


public class PipeException extends Exception {

    private static final long serialVersionUID = 8647786507719222800L;

    /**
     * 抛出异常的Pipe实例
     */
    public final Pipe<?, ?> sourcePipe;

    public final Object input;

    public PipeException(Pipe<?, ?> sourcePipe, Object input, String message) {
        super(message);
        this.sourcePipe = sourcePipe;
        this.input = input;
    }

    public PipeException(Pipe<?, ?> sourcePipe, Object input, String message, Throwable cause) {
        super(message, cause);
        this.sourcePipe = sourcePipe;
        this.input = input;
    }
}


/**
 * 对各个处理阶段的计算环境进行抽象,主要用于异常处理
 * @author huzhiqiang
 */
public interface PipeContext {
    public void handleError(PipeException exp);
}



/**
 * 测试代码
 * @author huzhiqiang
 *
 */
public class ThreadPoolBasedPipeExample {
    public static void main(String[] args) {
        final ThreadPoolExecutor threadPoolExecutor;
        threadPoolExecutor = new ThreadPoolExecutor(1, Runtime.getRuntime().availableProcessors()*2, 60, TimeUnit.MINUTES,
                new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy());

        final SimplePipeline<String, String> pipeLine = new SimplePipeline<String, String>();

        Pipe<String, String> pipe = new AbsractPipe<String, String>() {
            @Override
            public String doProcess(String input) throws PipeException {
                String result = input + "->[pipe1, " + Thread.currentThread().getName() + "]";
                System.out.println(result);
                return result;
            }
        };

        pipeLine.addAsThreadBasedPipe(pipe, threadPoolExecutor);

        pipe = new AbsractPipe<String, String>() {
            @Override
            public String doProcess(String input) throws PipeException {
                String result = input + "->[pipe2, " + Thread.currentThread().getName() + "]";
                System.out.println(result);

                try {
                    Thread.sleep(new Random().nextInt(100));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                return result;
            }
        };

        pipeLine.addAsThreadBasedPipe(pipe, threadPoolExecutor);

        pipe = new AbsractPipe<String, String>() {
            @Override
            public String doProcess(String input) throws PipeException {
                String result = input + "->[pipe3, " + Thread.currentThread().getName() + "]";
                System.out.println(result);

                try {
                    Thread.sleep(new Random().nextInt(200));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                return result;
            }

            @Override
            public void shutdown(long timeout, TimeUnit unit) {
                threadPoolExecutor.shutdown();

                try {
                    threadPoolExecutor.awaitTermination(timeout, unit);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        pipeLine.addAsThreadBasedPipe(pipe, threadPoolExecutor);

        pipeLine.init(pipeLine.newDefaultPipeContext());

        int N = 10;

        try {
            for(int i=0; i<N; i++){
                pipeLine.process("Task-" + i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        pipeLine.shutdown(10, TimeUnit.SECONDS);
    }
}
Pipeline 设计模式是一种将一个大型任务分解成多个小任务并将它们串联起来的设计模式。每个小任务都会处理一部分数据并将其传递给下一个任务,直到最终结果被生成。这种模式可以提高代码的可读性和可维护性,同时也可以提高代码的性能。 下面是一个简单的 Pipeline 设计模式的示例: ```java import java.util.ArrayList; import java.util.List; public class PipelineDemo { public static void main(String[] args) { List<String> input = new ArrayList<>(); input.add("apple"); input.add("banana"); input.add("cherry"); Pipeline<String, Integer> pipeline = new Pipeline<>(); pipeline.add(new StringLengthTask()) .add(new SquareTask()); List<Integer> output = pipeline.execute(input); System.out.println(output); } } interface Task<I, O> { O execute(I input); } class Pipeline<I, O> { private List<Task<?, ?>> tasks = new ArrayList<>(); public <T> Pipeline<I, T> add(Task<O, T> task) { tasks.add(task); return (Pipeline<I, T>) this; } public List<O> execute(List<I> input) { List<O> output = new ArrayList<>(); for (I i : input) { Object result = i; for (Task<?, ?> task : tasks) { result = task.execute(result); } output.add((O) result); } return output; } } class StringLengthTask implements Task<String, Integer> { @Override public Integer execute(String input) { return input.length(); } } class SquareTask implements Task<Integer, Integer> { @Override public Integer execute(Integer input) { return input * input; } } ``` 在这个示例中,我们定义了一个 Pipeline 类,它包含了一个任务列表。我们可以通过调用 add 方法来添加任务。execute 方法接受一个输入列表,并依次将每个输入传递给任务列表中的每个任务。最终结果被收集到一个输出列表中并返回。 在这个示例中,我们定义了两个任务:StringLengthTask 和 SquareTask。StringLengthTask 接受一个字符串并返回其长度,SquareTask 接受一个整数并返回其平方。我们将这两个任务添加到 Pipeline 中,并将一个字符串列表传递给 execute 方法。最终,我们得到了一个整数列表,其中包含了每个字符串的长度的平方。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值