项目笔记-java多线程处理

项目中遇到了一个关于多线程使用的问题,由于对这一块不熟,所以下个笔记记录一些。

需求大致如下:前端发送一个批量注册人员请求,java后台封装数据然后发送http请求到服务器进行注册。每一个请求最多处理10个人员,如果有批量注册一万个人,就要发送1000个请求。

处理方法:java后台固定跑5个线程(太多了处理服务器处理不过来)来处理这个功能,处理线程会一直去请求队列中查看是否有请求,如果有新请求就会唤醒处理线程处理,将处理结果存到结果队列,主线程等到所有请求都处理完了,再处理结果队列。

在这个例子中,我重写了一个demo来处理1~1,000,000,000累加,处理方法与上面的类似

处理该功能的主线程:

public class ImportThread extends Thread {

    //结果队列  Triplet:List<Integer>每线程执行结果,String进度json,Date更新时间用于定时
	public static Map<String,Triplet> mapList = new HashMap<>(); 
    public static List<Triplet> lstReq = new ArrayList<>(); //请求队列
    
    private Long total; //累加总数
    private Long per; //每个线程处理的数量
    private String uuid; //uuid代表某一次请求 请求队列、结果队列、进度队列都要用到
    
    ImportThread(Long total,Long per,String uuid){
    	this.total = total;
    	this.per = per;
    	this.uuid = uuid;
    }
    
    public void run(){
    	try{
    		mapList.put(uuid, new Triplet(new ArrayList<String>(),"",new Date()));
    		long size = total/per;
    		for(int i=0;i<size;i++){
    			Triplet triplet = new Triplet<>(uuid,i*per,(i+1)*per);
    			synchronized (lstReq){
    				lstReq.add(triplet); //将请求插入到请求队列中
    				lstReq.notifyAll(); //唤醒线程
    			}
    		}
    		
    		//处理返回结果
    		List<Long> result_ = null;
    		while(true){
    			//更新结果队列直到请求完成
    			Triplet resTriplet = mapList.get(uuid);
    			result_ = (List<Long>) resTriplet.getValue0();
    			JSONObject socketObject = new JSONObject();
    			float progress = result_.size()/(float)size*100;
    			socketObject.put("progress", String.format("%1.2f", progress));
    			socketObject.put("msg", result_.size()==size?"完成":"处理中");
    			Triplet newResult = new Triplet(result_,socketObject.toString(),new Date());
    			mapList.put(uuid, newResult);
    			if(result_.size()!=size){
    				Thread.sleep(1000);
    			}else{break;}
    		}
    		long sum=0;
    		for(long num:result_){
    			sum+=num;
    		}
    		System.out.println("结果:"+sum);
    	}catch(Exception e){
    		e.printStackTrace();
    	}
    }
}

处理线程:

public class BatchThread extends Thread {

	public void run(){
		Triplet triplet = null;
        while(true){
            try{
            	//每十秒查看请求队列是否有请求
                synchronized(ImportThread.lstReq) {
                    if(ImportThread.lstReq.isEmpty()) {
                        ImportThread.lstReq.wait(10000L);
                    }
                    if(!ImportThread.lstReq.isEmpty()) {
                        triplet = ImportThread.lstReq.remove(0);
                        System.out.println(String.format("请求队列还剩:%s",ImportThread.lstReq.size()));
                    }
                }

                if(triplet == null)continue;
                //业务代码  累加
                long start = (long) triplet.getValue1(); //开始值
                long end = (long) triplet.getValue2(); //结束值
                long sum = 0;
                for(long i=start;i<end;i++){
                	sum+=i;
                }
                Triplet tripletRes = ImportThread.mapList.get(triplet.getValue0());
                List<Long> result_ = (List<Long>) tripletRes.getValue0();	
                result_.add(sum);
                Triplet triplet1 = new Triplet(result_,tripletRes.getValue1(),new Date());
                
                //将结果放入结果队列中
                ImportThread.mapList.put((String) triplet.getValue0(), triplet1);
                Thread.sleep(500);//为了方便看结果,等待0.5s
            } catch (Exception e){
            	e.printStackTrace();
            }
            triplet = null;
        }
    }
}

获取进度线程(进度是通过前端定时调用接口返回,这里为了方便用线程做个模拟)

public class ProgressThread extends Thread {

	private String uuid;
	
	ProgressThread(String uuid){
		this.uuid = uuid;
	}
	
	public void run(){
		try{
			while(true){
				Triplet triplet = ImportThread.mapList.get(uuid);
				if(triplet==null){
					Thread.sleep(100);
					continue;
				}
				String progress = (String) triplet.getValue1();
				System.out.println(progress);
				JSONObject obj = new JSONObject(progress);
				String prg = obj.getString("progress");
				if(prg.equals("100.00")){
					break;
				}else{
					Thread.sleep(1000);
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

测试:

public class App 
{
    public static void main( String[] args )
    {
    	//整个系统固定分配3个线程跑这功能
        for(int i=0;i<3;i++){
        	new BatchThread().start();
        }
        new ImportThread(1000000000L,100000000L,"uuid").start();//启动执行线程
        //进度是通过前端定时调用接口返回,这里为了方便做个模拟
        new ProgressThread("uuid").start();;//启动获取进度线程
        
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值