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