java 多线程并发实现(1)

背景

我们在开发中常常会遇到针对某个服务出现响应时间过长,用户使用体验感极差,出现这种问题的原因比较多,我们现在就说一下其中的一种情况,for循环遍历查询。

前提

首先先来简单介绍一个多线程,提到多线程,首先要明白这几个词汇的意思,进程,线程,并发,并行,多线程,同步。

进程:简单来讲,就是一个正在进行中的程序,比如请求一次接口。

线程:进程中独立运行的一个子任务就是一个线程,比如请求一次接口的过程就可以是一个线程,也可以启动多个线程。

并发:指两个或多个事件在同一时间段内执行。

并行:值两个或多个时间在同一时间点执行。

同步:通过人为的控制使多线程访问公共资源时保证线程安全,比如在公共方法上加锁(synchronized),线程安全是优化线程性能的前提。

优化前代码

JSONArray devices = req.getJSONArray("devices");
if(null!=devices&&!devices.isEmpty()){    
    for(Object device:devices){
        saveTodayAICalculate(device);   //循环执行方法
    }    
}

//方法
public void saveTodayAICalculate(JSONObject device){
    //执行方法内容
    xxx...
}

优化后代码

JSONArray devices = req.getJSONArray("devices");
if(null!=devices&&!devices.isEmpty()){
    try{
        ExecutorService es = Executors.newFixedThreadPool(8); //定义线程池
        CountDownLatch cdld = new CountDownLatch(devices.size());
        for(Object device:devices){
            es.execute(new Runnable(){
                @Override
                public void run() {
                          saveTodayAICalculate(device,cdld); //执行线程方法
                }
            });
        }
        cdld.await();
    }catch(Exception e){
        logger.error("execute executorServcice error,reason is {}",e);
    }finally{
        es.shutdown(); //执行完一定要销毁线程,不然容易出现内存溢出异常
    }  
}

//线程执行方法
public void saveTodayAICalculate(JSONObject device,CountDownLatch cdl){
    try{
        xxx...
    }catch(Exception e){
        xxx...
    }finally{
        if(null!=cdl){
            cdl.countDown();
        }
    }
}

说明

1 通过java.util.cocarrent.Executors创建线程池ExecutorService,创建的方式有多种,这里只使用newFixedThreadPool穿件固定大小线程池。

2 使用countDownLatch控制线程的执行。

3 多线程执行完一定要销毁线程池,不然会出现内存溢出异常。

总结一下,这种多线程的缺陷一是当并发量多时,容易创建大量的线程池,占用大量cpu和内存,二是当执行线程需要返回数据时不满足,这种情况可以通过实现Callable接口,然后通过Future获取返回值。比如:

ExecutorService es = Executors.newFixedThreadPool(8);
List<Future<String>> tasks = new ArrayList<>();
for(int i=0;i<12;i++){
    Future<String> future = es.submit(new MyCallable(i));
    tasks.add(future);
}
for(Future<String> future : tasks){
    System.out.println(future.get());
}

//线程类
public class MyCallable implements Callable<String> {
    private Integer k;
    public MyCallable(Integer k){
        this.k = k;
    }
    @Override
    public String call() throws Exception {
        return this.k +":"+ this.toString();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值