并行程序设计模式

Future模式

Future模式理念

Future模式是一种比较常用的手法。类似在家里煮饭一般,当你把饭放入电饭煲中进行焖煮,你就可以抽出时间去摘菜、切片等,待饭煮熟了,再进行炒菜,将时间充分利用。

简单代码实现

  • Future模式主要参与者
参与者作用
Main系统启动,调用Client发出请求
Client返回Data对象,立即返回FutureData,并开启ClientThread线程装配RealData
Data返回数据的接口
FutureDataFuture数据,构造很快,但是是一个虚拟的数据,需要装配RealData
RealData真实数据,其构造比较慢
  • 类图

FutureData模式结构图

  • 代码实现
public class Main {


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Client client = new Client();
        Data data = client.request("name","a1");
        System.out.println("请求完毕 " );
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("在等数据: " );
        System.out.println("数据 = " + data.getResult());

    }

}
public class Client {

    public Data request(final String queryStr, final String name) {
        final FutureData futureData = new FutureData();
        new Thread(name) {
            @Override
            public void run() {
                RealData realData = new RealData(queryStr);

                futureData.setRealData(realData);
            }
        }.start();

        return futureData;
    }
}
public interface Data {

    String getResult();
}

public class FutureData implements Data{
    protected RealData realData = null;
    protected boolean isReady = false;

    public void setRealData(RealData realData) {
        if(isReady){
            return;
        }
        this.realData = realData;
        isReady= true;
        notifyAll();
    }

    @Override
    public synchronized String getResult() {
        while (!isReady){
            try {
                wait();
            }catch (InterruptedException e){

            }
        }
        return realData.result;
    }
}
public class RealData implements Data {

    protected final String result;

    public RealData(String para) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 10; i++) {
            sb.append(para);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        result = sb.toString();
    }

    @Override
    public String getResult() {
        return result;
    }
}

JDK的内置实现

JDK内置的Future模式 除了基本的功能外,它还可以取消任务,或者设定Future任务的超时时间。其基本用法如下:

public class RealDataJdk implements Callable<String> {

    private String para;

    public RealDataJdk(String para) {
        this.para = para;
    }

    @Override
    public String call() throws Exception {

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 10; i++) {
            sb.append(para);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }
}
public class Main {


    public static void main(String[] args) throws ExecutionException, InterruptedException {
   
        // jdk 使用
        FutureTask<String> futureTask = new FutureTask<>(new RealDataJdk("jdk"));
        ExecutorService service = Executors.newFixedThreadPool(1);
        service.submit(futureTask);
        System.out.println("请求完毕 " );
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("在等数据: " );
        System.out.println("数据 = " + futureTask.get());
        service.shutdown();
    }

}

Master-Worker模式

Master-Worker模式理念

Master-Worker模式核心思想是系统由2类进程协作完成:Master进程和Worker进程。Master进程主要负责接收和分配任务,Worker进程负责处理子任务。当各个Worker进程处理子任务完成后,将结果返回给Master进程做归纳和汇总,从而得到系统最终结果。
Master-Worker模式图

简单代码实现

  • Future模式主要参与者
参与者作用
Main系统启动,调度开启Master
Master用于任务的分配和最终结果的合成
Worker用于实际处理一个任务
  • 代码实现
public class Master {

    /**
     * 任务队列
     */
    protected Queue<Object> workQueue = new ConcurrentLinkedQueue<>();
    /**
     * Worker 进程队列
     */
    protected Map<String, Thread> threadMap = new HashMap<String, Thread>();
    /**
     * 子任务处理结果集
     */
    protected Map<String, Object> resultMap = new ConcurrentHashMap<String, Object>();

    public boolean isComplete() {
        for (Map.Entry<String, Thread> entry : threadMap.entrySet()) {
            if (entry.getValue().getState() != Thread.State.TERMINATED) {
                return false;
            }
        }
        return true;
    }


    public Master() {
    }


    /**
     * Master的构造,需要一个Worker进程逻辑,和需要Worker进程数量
     * @param worker
     * @param countWorker
     */
    public Master(Worker worker, int countWorker) {

        worker.setWorkQueue(workQueue);
        worker.setResultMap(resultMap);
        for (int i = 0; i < countWorker; i++) {
            threadMap.put(Integer.toString(i), new Thread(worker, Integer.toString(i)));
        }

    }

    //提交一个任务
    public void submit(Object job) {
        workQueue.add(job);
    }


    //返回子任务结果集
    public Map<String, Object> getResultMap() {
        return resultMap;
    }


    //开始运行所有的Worker进程,进行处理
    public void execute() {
        for (Map.Entry<String, Thread> entry : threadMap.entrySet()) {
            entry.getValue().start();

        }
    }
}

public class Worker implements Runnable {

    //任务队列,用于取得子任务
    protected Queue<Object> workQueue;
    //子任务处理结果集
    protected Map<String, Object> resultMap;

    public void setWorkQueue(Queue<Object> workQueue) {
        this.workQueue = workQueue;
    }

    public void setResultMap(Map<String, Object> resultMap) {
        this.resultMap = resultMap;
    }

    //子任务处理的逻辑,在子类中实现具体逻辑
    public Object handle(Object input) {
        return input;
    }


    @Override
    public void run() {

        while (true) {
            //获取子任务
            Object input = workQueue.poll();
            if (input == null) {
                break;
            }
            //处理子任务
            Object re = handle(input);
            resultMap.put(Integer.toString(input.hashCode()), re);
        }
    }

}
public class PlusWorker extends Worker {

    @Override
    public Object handle(Object input) {
        System.out.println(Thread.currentThread().getName() + " = " + input);
        Integer i = (Integer) input;
        return i * i * i;
    }

}

public class Main {

    public static void main(String[] args) {
        long l = System.currentTimeMillis();

        //固定使用5个Worker,并指定Worker
        Master m = new Master(new PlusWorker(), 5);
        //提交100个子任务
        for (int i = 0; i < 100; i++) {
            m.submit(i);
        }
        //开始计算
        m.execute();
        long re = 0;
        //保存最终结算结果
        Map<String, Object> resultMap = m.getResultMap();

        //不需要等待所有Worker都执行完成,即可开始计算最终结果
        while (resultMap.size() > 0 || !m.isComplete()) {
            Set<String> keys = resultMap.keySet();
            String key = null;
            for (String k : keys) {
                key = k;
                break;
            }
            Integer i = null;
            if (key != null) {
                i = (Integer) resultMap.get(key);
            }
            if (i != null) {
                //最终结果
                re += i;
            }
            if (key != null) {
                //移除已经被计算过的项
                resultMap.remove(key);
            }

        }

        System.out.println("结果 : " + re);
        System.out.println(System.currentTimeMillis() - l);
    }


}

Guarded Suspension模式

Guarded Suspension模式理念

Guarded Suspension意为暂停保护,其核心思想是仅当服务进程准备好时,才提供服务。类似如当一个web服务短时间内接收到大量客户端请求时,当前请求数远大于本身处理能力了,服务端又不能丢弃任何一个客户请求,此时,最佳处理方案莫过于让客户端排队请求,服务端挨个处理。

简单代码实现

  • Guarded Suspension模式主要参与者
参与者作用
Request表示客户端请求
RequestQueue用于保存客户端请求队列
ClientThread客户端进程
ServerThread服务端进程
  • 代码实现
public class Request {
    private String name;

    public Request(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Request{" +
                "name='" + name + '\'' +
                '}';
    }
}

public class RequestQueue {
    private LinkedList queue = new LinkedList();

    public synchronized Request getRequest(){
        while (queue.size() == 0){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return (Request) queue.remove();
    }

    public synchronized void addRequest(Request request){
        queue.add(request);
        notifyAll();
    }

}
public class ClientThread extends Thread{

    private RequestQueue requestQueue;

    public ClientThread(RequestQueue requestQueue, String name){
        super(name);
        this.requestQueue = requestQueue;
    }

    @Override
    public void run() {
        for (int i=0;i<10;i++){
            Request request = new Request("RequestId:"+i+" Thread_Name:"+Thread.currentThread().getName());
            System.out.println(Thread.currentThread().getName() + " request "+ request);
            requestQueue.addRequest(request);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + " request end");
    }
}
public class ServerThread extends Thread {

    private RequestQueue requestQueue;

    public ServerThread(RequestQueue requestQueue, String name) {
        super(name);
        this.requestQueue = requestQueue;
    }

    @Override
    public void run() {
        while (true) {
            final Request request = requestQueue.getRequest();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + " handles " + request);
        }
    }


    public static void main(String[] args) {
        RequestQueue requestQueue = new RequestQueue();
        for (int i = 0; i < 10; i++) {
            new ServerThread(requestQueue, "ServerThread" + i).start();
        }

        for (int i = 0; i < 10; i++) {
            new ClientThread(requestQueue, "ClientThread" + i).start();
        }
    }
}

不变模式

不变模式理念

在并行软件开发过程中,同步操作似乎是必不可少的。当多线程对同一个对象进行读写操作时,未来保证对象数据的一致性和正确性,有必要对对象进行同步操作。而同步必然引起性能损耗,所以可以使用不可改变的对象,依靠对象的不变性,可以确保其在没有同步操作的多线程环境中始终保持内部状态的一致性和正确性,这就是不变模式。
不变模式满足以下2个条件:

  • 当对象创建后,其内部状态和数据不再发生任何变化
  • 对象需要被共享、被多线程频繁访问。
    在jdk中采用了不变模式的类型如下:
  1. java.lang.String
  2. java.lang.Boolean
  3. java.lang.Byte
  4. java.lang.Character
  5. java.lang.Double
  6. java.lang.Float
  7. java.lang.Integer
  8. java.lang.Long
  9. java.lang.Short

生产者-消费者模式

生产者-消费者模式理念

生产者-消费者是一个经典的多线程设计模式,它为多线程间的协作提供了良好的解决方案。其基本组成为若干个生产者线程和若干个消费者线程,之间通过共享内存缓冲区进行通信
生产者与消费者模式图

简单代码实现

  • 生产者与消费者模式主要参与者
参与者作用
生产者用户用户提交请求,将任务放进缓冲区中
消费者从缓冲区中提取任务并处理任务
内存缓冲区作为中间媒介
任务基本数据结构
Main使用生产者和消费者
  • 代码实现
public class Producer implements Runnable {

    private volatile boolean isRunning = true;

    private BlockingQueue<PCData> queue;

    private static AtomicInteger atomicInteger = new AtomicInteger();

    private static final int SLEEPTIME = 1000;

    public Producer(BlockingQueue<PCData> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        PCData data = null;
        Random random = new Random();

        System.out.println("start producer id = " + Thread.currentThread().getId());

        try {
            while (isRunning) {
                Thread.sleep(random.nextInt(SLEEPTIME));
                data = new PCData(atomicInteger.incrementAndGet());
                System.out.println(data + " is put into queue");
                if (!queue.offer(data, 2, TimeUnit.SECONDS)) {
                    System.err.println("failed to put data" + data);
                }

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }

    }

    public void stop() {
        isRunning = false;
    }
}
public class Consumer implements Runnable {

    private BlockingQueue<PCData> queue;
    private static final int SLEEPTIME = 1000;

    public Consumer(BlockingQueue<PCData> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        System.out.println("start Consumer id = " + Thread.currentThread().getId());
        Random r = new Random();
        try {
            while (true) {
                PCData data = queue.take();
                if (null != data) {
                    int i = data.getIntData() * data.getIntData();
                    System.out.println(MessageFormat.format("线程{3}:{1}*{1}={2}", data.getIntData(), data.getIntData(), i, Thread.currentThread().getId()));
                    Thread.sleep(r.nextInt(SLEEPTIME));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }

    }
}

public final class PCData {
    private final int intData;

    public PCData(int intData) {
        this.intData = intData;
    }

    public int getIntData() {
        return intData;
    }

    @Override
    public String toString() {
        return "PCData{" +
                "intData=" + intData +
                '}';
    }
}

public class Main {

    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<PCData> queue = new LinkedBlockingQueue<>(10);
        Producer producer1 = new Producer(queue);
        Producer producer2 = new Producer(queue);
        Producer producer3 = new Producer(queue);
        Consumer consumer1 = new Consumer(queue);
        Consumer consumer2 = new Consumer(queue);
        Consumer consumer3 = new Consumer(queue);
        ExecutorService service = Executors.newCachedThreadPool();
        service.submit(producer1);
        service.submit(producer2);
        service.submit(producer3);
        service.submit(consumer1);
        service.submit(consumer2);
        service.submit(consumer3);
        Thread.sleep(10 * 1000);
        producer1.stop();
        producer2.stop();
        producer3.stop();
        Thread.sleep(3000);
        service.shutdown();

    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值