Java多线程之主从设计模式-yellowcong

来源:互联网 发布:unity3d htc vive开发 编辑:程序博客网 时间:2024/05/21 08:59

在Hadoop和Redis等集群的时候,都会有主从的概念,有一个主节点用于控制请求的分发和结果的统计,从节点用于真正的数据处理操作。在多线程中,我们可以把 一个大任务分割成多个小任务,给子节点处理,在这种设计模式中,我们需要使用到原子类 ConcurrentLinkedQueue (用于存储请求提交的任务),和ConcurrentHashMap(用于收集每一个节点获取的结果)。在这种无锁的设计模式中,必须用到原子类的对象,解决数据的统一问题

在多线程开发中,需要多使用原子类解决问题,而不是使用锁的方式来解决,锁的方式效率相对比较低,notify和wait方式远不及Lock类的锁,所以开发中,能使用到原子类的,尽量用原子类完成。

任务对象

任物对象,只是一个简单的java bean,没有任何的复杂处理,这个案例设计的是,有一个加法运算,分成多个任务,通过Work线程完成

package com.yellowcong.work;/** * 创建日期:2017年10月6日 <br/> * 创建用户:yellowcong <br/> * 功能描述:任务队列 */public class Task {    private String name;    private String id;    private Integer price;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getId() {        return id;    }    public void setId(String id) {        this.id = id;    }    public Integer getPrice() {        return price;    }    public void setPrice(Integer price) {        this.price = price;    }}

Master类

主对象中,必须有三个重要的对象
1、ConcurrentLinkedQueue<Task> ,收集任务队列,将所有提交的任务都会放到这个队列中
2、HashMap<String, Thread> 来维护 Master管理的Work对象(任务处理节点,判断主节点可以管理多少个小弟完成人物),在添加任务后,可以遍历这个对象的线程,启动Work任务
3、ConcurrentHashMap<String, Object> 用于收集每个Work节点处理的结果,然后在主节点中做统计处理

package com.yellowcong.work;import java.security.KeyStore.Entry;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentLinkedQueue;/** * 创建日期:2017年10月6日 <br/> * 创建用户:yellowcong <br/> * 功能描述:   */public class Master {    //1.任务管理    private ConcurrentLinkedQueue<Task> tasks =  new ConcurrentLinkedQueue<Task>();    //2.master来管理的Works     private HashMap<String, Thread> works = new HashMap<String, Thread>();    //3.用这个容器来接收处理 完成的任务的结果集    private ConcurrentHashMap<String, Object> results = new ConcurrentHashMap<String, Object>();    //4、设定人物和启动的线程数量    public Master(Work work,int count) {        //每个work里面需要有 放result和获取人物的队列        work.setResults(results);        work.setTasks(tasks);        //将多个线程的Work都放到HashMap集合中        for(int i=0;i<count;i++){            //key 是节点的名字, val是多线程            works.put(String.valueOf(i),new Thread(work));        }    }    //5、提交任务    public void submit(Task task){        this.tasks.add(task);    }    //6、启动任务    public void execute(){        for(Map.Entry<String, Thread> entry :works.entrySet()){            //启动所有线程            entry.getValue().start();        }    }    //7.判断线程是否完毕    public boolean isComplite(){        for(Map.Entry<String, Thread> entry :works.entrySet()){            // 线程执行完毕或异常退出会进入终止状态 ,判断是否是终止状态            if(entry.getValue().getState() != Thread.State.TERMINATED){                return false;            }        }        return true;    }    //8.返回结果数据    public long getResult(){        long data = 0l;        for(Map.Entry<String, Object> entry :results.entrySet()){            data += Long.parseLong(String.valueOf(entry.getValue().toString()));        }        return data;    }}

Work 类

这个类实现了Runable接口,在这个里面,有
ConcurrentHashMap<String, Object>
ConcurrentLinkedQueue<Task>
这两个集合对象,是由Master传递过来,目的 是为了获取任务和将任务处理的结果存储起来

package com.yellowcong.work;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentLinkedQueue;/** * 创建日期:2017年10月6日 <br/> * 创建用户:yellowcong <br/> * 功能描述:Master所管理的类,Master的人物都分派给Work做 */public class Work implements Runnable {    private ConcurrentHashMap<String, Object> results;    private ConcurrentLinkedQueue<Task> tasks;    public void setResults(ConcurrentHashMap<String, Object> results) {        this.results = results;    }    public void setTasks(ConcurrentLinkedQueue<Task> tasks) {        this.tasks = tasks;    }    public void run() {        while(true){            //当任务为空的情况            if(tasks.isEmpty()){                break;            }            //获取一个任务            Task task = this.tasks.poll();            Object result = haddle(task);            //设定结果            this.results.put(task.getId(), result);        }    }    /**     * 真正处理事情的逻辑     * 创建日期:2017年10月6日<br/>     * 创建用户:yellowcong<br/>     * 功能描述:     * @param task     * @return     */    private Object haddle(Task task) {        try {            Thread.sleep(500);        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return task.getPrice();    }}

测试类

测试类中,启动了10个 Work对象,来完成整个任务,当线程数量增加时,整体锁用的时间,就会减少。

package com.yellowcong.work;import java.util.Random;/** * 创建日期:2017年10月6日 <br/> * 创建用户:yellowcong <br/> * 功能描述:   */public class MainTest {    public static void main(String[] args) {        System.out.println(Thread.activeCount());        //建立一个主节点        Master master = new Master(new Work(), 10);        Random rand = new Random();        for(int i=0;i<100;i++){            Task task = new Task();            task.setId(String.valueOf(i));            task.setName("任务"+i);            task.setPrice(rand.nextInt(1000));            //提交任务            master.submit(task);        }        //执行任务        long start = System.currentTimeMillis();        master.execute();        //判断是否执行完成        while(true){            if(master.isComplite()){                long result = master.getResult();                long end = System.currentTimeMillis();                System.out.println("最终结果"+result+",耗时"+Long.toString(end-start));                break;            }        }    }}