Java高并发之设计模式(2)

public String costTime() {
        try {
            // 模拟RealData耗时操作
            Thread.sleep(1000L);
            return "result";
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "exception";
    }

}

通过Future实现

与上述FutureTask不同的是, RealData需要实现Callable接口.

public class FutureDemo2 {

public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService service = Executors.newCachedThreadPool();
        Future<String> future = service.submit(new RealData2());

System.out.println("RealData2方法调用完毕");
        // 模拟主函数中其他耗时操作
        doOtherThing();
        // 获取RealData2方法的结果
        System.out.println(future.get());
    }

private static void doOtherThing() throws InterruptedException {
        Thread.sleep(2000L);
    }
}

class RealData2 implements Callable<String>{

public String costTime() {
        try {
            // 模拟RealData耗时操作
            Thread.sleep(1000L);
            return "result";
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "exception";
    }

@Override
    public String call() throws Exception {
        return costTime();
    }
}

另外Future本身还提供了一些额外的简单控制功能, 其API如下

// 取消任务
    boolean cancel(boolean mayInterruptIfRunning);
    // 是否已经取消
    boolean isCancelled();
    // 是否已经完成
    boolean isDone();
    // 取得返回对象
    V get() throws InterruptedException, ExecutionException;
    // 取得返回对象, 并可以设置超时时间
    V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;

生产消费者模式

生产者-消费者模式是一个经典的多线程设计模式. 它为多线程间的协作提供了良好的解决方案。

在生产者-消费者模式中,通常由两类线程,即若干个生产者线程和若干个消费者线程。

生产者线程负责提交用户请求,消费者线程则负责具体处理生产者提交的任务。

生产者和消费者之间则通过共享内存缓冲区进行通信, 其结构图如下

Java高并发之设计模式

PCData为我们需要处理的元数据模型, 生产者构建PCData, 并放入缓冲队列.

消费者从缓冲队列中获取数据, 并执行计算.

生产者核心代码

while(isRunning) {
            Thread.sleep(r.nextInt(SLEEP_TIME));
            data = new PCData(count.incrementAndGet);
            // 构造任务数据
            System.out.println(data + " is put into queue");
            if (!queue.offer(data, 2, TimeUnit.SECONDS)) {
                // 将数据放入队列缓冲区中
                System.out.println("faild to put data : " + data);
            }
        }

消费者核心代码

while (true) {
            PCData data = queue.take();
            // 提取任务
            if (data != null) {
                // 获取数据, 执行计算操作
                int re = data.getData() * 10;
                System.out.println("after cal, value is : " + re);
                Thread.sleep(r.nextInt(SLEEP_TIME));
            }
        }

生产消费者模式可以有效对数据解耦, 优化系统结构.

降低生产者和消费者线程相互之间的依赖与性能要求.

一般使用BlockingQueue作为数据缓冲队列, 他是通过锁和阻塞来实现数据之间的同步, 

如果对缓冲队列有性能要求, 则可以使用基于CAS无锁设计的ConcurrentLinkedQueue.

分而治之

严格来讲, 分而治之不算一种模式, 而是一种思想.

它可以将一个大任务拆解为若干个小任务并行执行, 提高系统吞吐量.

我们主要讲两个场景, Master-Worker模式, ForkJoin线程池.

Master-Worker模式

该模式核心思想是系统由两类进行协助工作: Master进程, Worker进程.

Master负责接收与分配任务, Worker负责处理任务. 当各个Worker处理完成后, 

将结果返回给Master进行归纳与总结.

Java高并发之设计模式

假设一个场景, 需要计算100个任务, 并对结果求和, Master持有10个子进程.

Master代码

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/083e568311e9022afc3de0ec21a754aa.html