7.多线程的设计模式

本文深入探讨了Future模式和Master-Worker模式的工作原理及应用实例。Future模式通过异步处理请求,允许主程序在等待响应时执行其他任务,提高效率。Master-Worker模式则是一种并行处理策略,通过任务队列分配工作给多个工作者线程,最后汇总结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Future模式

说明:

例子:

//主函数
public class Main {

	public static void main(String[] args) throws InterruptedException {
		
		FutureClient fc = new FutureClient();
		Data data = fc.request("请求参数");
		System.out.println("请求发送成功!");
		System.out.println("做其他的事情...");
		
		String result = data.getRequest();
		System.out.println(result);
		
	}
}

//data接口
public interface Data {

	String getRequest();

}

//2个实现了Data接口的类


public class FutureData implements Data{

	private RealData realData ;
	
	private boolean isReady = false;
	
	public synchronized void setRealData(RealData realData) {
		//如果已经装载完毕了,就直接返回
		if(isReady){
			return;
		}
		//如果没装载,进行装载真实对象
		this.realData = realData;
		isReady = true;
		//进行通知
		notify();
	}
	
	@Override
	public synchronized String getRequest() {
		//如果没装载好 程序就一直处于阻塞状态
		while(!isReady){
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		//装载好直接获取数据即可
		return this.realData.getRequest();
	}


}


public class RealData implements Data{

	private String result ;
	
	public RealData (String queryStr){
		System.out.println("根据" + queryStr + "进行查询,这是一个很耗时的操作..");
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("操作完毕,获取结果");
		result = "查询结果";
	}
	
	@Override
	public String getRequest() {
		return result;
	}

}




//另起线程去做事
public class FutureClient {

	public Data request(final String queryStr){
		//1 我想要一个代理对象(Data接口的实现类)先返回给发送请求的客户端,告诉他请求已经接收到,可以做其他的事情
		final FutureData futureData = new FutureData();
		//2 启动一个新的线程,去加载真实的数据,传递给这个代理对象
		new Thread(new Runnable() {
			@Override
			public void run() {
				//3 这个新的线程可以去慢慢的加载真实对象,然后传递给代理对象
				RealData realData = new RealData(queryStr);
				futureData.setRealData(realData);
			}
		}).start();
		
		return futureData;
	}
	
}


输出结果:
请求发送成功!
做其他的事情...
根据请求参数进行查询,这是一个很耗时的操作..
操作完毕,获取结果
查询结果






2.master-worker模式

 

例子:

public class Master {

    //1,应该有一个承装任务的集合
   private ConcurrentLinkedQueue<Task> taskQueue= new ConcurrentLinkedQueue<Task>();

    //2 需要有一个盛放worker的集合
    private HashMap<String, Thread> workers = new HashMap<String, Thread>();

    //3 需要有一个盛放每一个worker执行任务的结果集合
  private ConcurrentHashMap<String, Object>  resultMap = new ConcurrentHashMap<String, Object> ();

  //4.构造方法 放work
    public Master(Worker worker,int workCount){
        //每个worker对象要有taskQueue的引用,用于取任务
        //resultMap用于任务的提交
        worker.setTaskQueue(taskQueue);
        worker.setResultMap(resultMap);
        for (int i = 0; i <workCount ; i++) {
          //key表示worker的名字,value表示线程执行对象
            workers.put("work"+i,new Thread(worker));
        }
    }

    //5.提交方法,用于往队列里面添加任务
    public  void submit(Task task){
        this.taskQueue.add(task);
    }


   //6.需要有一个执行的方法,让所有的worker去执行任务task
    public void execute(){

        for(Map.Entry<String,Thread> me : workers.entrySet()){
            me.getValue().start();
        }
    }


    //7判断线程是否都执行完
    public boolean isComplete() {
        for(Map.Entry<String,Thread> me : workers.entrySet()){
            if (me.getValue().getState()!=Thread.State.TERMINATED){
                return false;
            }
        }
        return true;
    }

    //8.返回结果集
    public int getResult(){
        int ret=0;
        for(Map.Entry<String,Object> me : resultMap.entrySet()){
            ret+= (Integer)me.getValue();
        }
        return ret;
    }


//任务类

public class Task {

    private int id;
    private String name;
    private int price ;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }

    public String getName() {
        return name;
    }

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


//work类 执行任务

public class Worker implements Runnable {

    private ConcurrentLinkedQueue<Task> taskQueue;
    private ConcurrentHashMap<String, Object> resultMap ;




    public void setTaskQueue(ConcurrentLinkedQueue<Task> taskQueue) {
        this.taskQueue = taskQueue;
    }



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

    @Override
    public void run() {

        while (true){
            //取出元素并且移除
            Task input = this.taskQueue.poll();
            if (input==null) break ;
            //真正的去处理业务
            Object output = handle(input);
            this.resultMap.put(Integer.toString(input.getId()),output);

        }
    }

    private Object handle(Task input) {
        Object output=null;
        try {
            //模拟处理task的时间
            Thread.sleep(1000);
            output= input.getPrice();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return  output;
    }
}


//主函数

public class Main {


    public static void main(String[] args) {

        //20个处理器
      Master master=  new Master(new Worker(), 20);

        Random random = new Random();
        //100个任务
        for (int i = 1; i <=100 ; i++) {
            Task task= new Task();
            task.setId(i);
            task.setName("任务"+i);
            task.setPrice(random.nextInt(1000));
            master.submit(task);
        }

        //执行 让10个work去取任务
        master.execute();

        long start = System.currentTimeMillis();
        //判断任务是否都执行完了
        while (true){
            if (master.isComplete()){
                int result = master.getResult();
                System.out.println("结果为:"+result+"执行时间:"+(System.currentTimeMillis()-start)+"毫秒");
                break;
            }
        }

    }
}


//运行结果:

结果为:50643执行时间:5006毫秒

改变Worker的个数,时间会不一样 


说明:这个例子比较简单。。

100个任务放在了 ConcurrentLinkedQueue 里面  

每个worker线程用于处理任务,这里新建了20个work,HashMap<String, Thread>用于存放work。
ConcurrentHashMap<String, Object>用于放处理之后的结果集,之所以用ConcurrentHashMap,是因为20个线程并发放map里面放东西。

循环装work的map用Thread.State.TERMINATED判断线程状态是否终止。

用sleep模仿每个线程执行1秒,100个任务100秒,20个线程去跑,每个线程大约5秒符合

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值