在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;
            }
        }

    }
}