精华内容
下载资源
问答
  • 2018-11-20 17:31:57

    测试经常遇到查看大数据量URL请求是否正常。单线程跑的太慢

    可以自定义线程数进行跑,细节不多说,其实我也是上网上凑的,拿下来修修改改能用即可。

    #!/bin/bash
    ttime=`date +"%Y-%m-%d %H:%M:%S"`
    #允许的线程数
    THREAD_NUM=5
    #定义描述符为9的管道
    mkfifo tmp
    exec 9<>tmp
    #预先写入指定数量的换行符,一个换行符代表一个进程
    for((i=0;i<$THREAD_NUM;i++))
    do
            echo -ne "\n" 1>&9
    done
    
    if [ $# -ne 1 ]
    then
            echo "The parameters you enter is not correct!";
            exit -1;
    fi
    
    while read line
    do
    {
            #进程控制
            read -u 9
            {
            isok=`curl -I -o /dev/null -s -w %{http_code} $line`
            if [ $isok = "200" ];then
                    echo $line "OK"
            else
                    echo $line "no"
            fi
            echo -ne "\n" 1>&9
    
            }&
    }
    done <$1
    wait
    echo "执行结束"
    rm -rf  tmp
    

     

    更多相关内容
  • C#(也称Csharp)在多线程下并发执行HTTP请求的实现,采用C#封装HttpWebRequest类开发的多线程并发采集程序源码文档,文档中详细说明了HttpWebRequest并发HTTP请求实现网站采集的方法,经过测试同时并发1000+不是问题...
  • 通过HTTP多线程并发post/get数据

    热门讨论 2013-09-27 11:35:30
    编译工具:VC++6.0 通过http进行多线程并发post/get数据从服务器上,并将数据显示在界面上。
  • 多线程处理多次Http请求慢的问题

    千次阅读 2020-06-17 13:44:22
    业务场景:前端调Java接口,接口需要多次请求http请求,因为是顺序执行,每个http耗时很长,大概5秒左右,但是叠加起来是很恐怖的,有必要做成多线程去处理。 大体思路:多线程去do任务,使用CountDownLatch进行...

    业务场景:前端调Java接口,接口需要多次请求http请求,因为是顺序执行,每个http耗时很长,大概5秒左右,但是叠加起来是很恐怖的,有必要做成多线程去处理。

    大体思路:多线程去do任务,使用CountDownLatch进行计数当前线程执行结束,然后调用await()方法,继续向下执行

    上代码:

    public String picMark(Model model, HttpServletRequest request) throws Exception {
        Map<String,Object> paramPicMap = picAssessService.getParamPic();//查库
        CountDownLatch latch=new CountDownLatch(2);
        Worker worker1=new Worker("DAMO", latch,paramPicMap);//走http比较慢
        Worker worker2=new Worker("YUSHI",  latch,paramPicMap);//走http比较慢
        worker1.start();//
        worker2.start();//
        //步骤3、4、调用await放过,等待所有线程完成工作
        latch.await();
        if(worker1.resultList == null  && worker2.resultList == null ){
           model.addAttribute("message","暂无可标注的数据");
        }
        model.addAttribute("picAssessList",worker1.resultList);
        model.addAttribute("newPicAssessList",worker2.resultList);
        model.addAttribute("paramPicUrl",paramPicMap.get("url"));
        return "modules/beyond/picAssess/picAssessForm";
    }
    class Worker extends Thread{
        CountDownLatch latch;
        String algorithmType;
        List resultList;
        Map<String,Object> paramPicMap;
        public Worker(String algorithmType,CountDownLatch latch,Map<String,Object> paramPicMap){
            this.algorithmType=algorithmType;
            this.latch=latch;
            this.paramPicMap=paramPicMap;
        }
        @Override
        public void run(){
            doWork(algorithmType,paramPicMap);//工作逻辑方法
            latch.countDown();//每完成一次减1
        }
    
        private void doWork(String algorithmType,Map<String,Object> paramPicMap){
            try {
                if("DAMO".equals(algorithmType)){
                    this.resultList=picAssessService.getSearchPicList(paramPicMap);//实际需要走http的方法,很耗时
                }else if("YUSHI".equals(algorithmType)){
                    this.resultList=picAssessService.getNewSearchPicList(paramPicMap);//实际需要走http的方法,很耗时
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    使用后耗时减少了近一倍,当http越多节省的时间越多!!

     

    展开全文
  • springmvc+spring线程池处理http并发请求数据同步控制问题
  • 最近做android,有一个问题一直...服务器怎么一下子处理这些请求,而服务器如果是多线程处理完这些请求返回到客户 端时,客户端怎么知道这些返回信息是返回给哪个客户端线程的,毕竟它们SessionId和请求 地址是一样的?
  • Servlet对并发的处理Tomcat容器处理多并发采用单例模式、多线程处理方式只要webapp被发布到web容器中的时候,servlet只会在发布的时候实例化一次,servlet在其生命周期中只有在将项目给移除或服务器stop的时候才会...

    Servlet对并发的处理

    Tomcat容器处理多并发采用单例模式、多线程处理方式

    只要webapp被发布到web容器中的时候,servlet只会在发布的时候实例化一次,servlet在其生命周期中只有在将项目给移除或服务器stop的时候才会销毁,那么一个web项目从发布到运行只存在一个servlet的实例。

    servlet容器中包含有线程池,规定了线程池当中承载线程的数量

    当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread) 调度它管理下线程池中等待执行的线程(Worker Thread)给请求者

    出现不同的线程同一时间访问同一个servlet的时候,其实servlet的对象只有一个,但是由于是tomcat支持多线程的原因,每个客户端请求执行的servlet中的函数都是在自己所支配的那一小段线程里面执行了,也就是说两个用户都登陆,都访问login方法,但是这是有用的是一个servlet但是局部的方法是放在不同的线程里面的。

    也就是说,整个过程servlet实例只有一个,供多个线程使用,每次servlet被访问都会被线程池的操作线程选出并提供一个新的线程进行操作

    servlet是线程安全的吗?

    Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。

    当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类,也就是有多个线程在使用这个实例。Servlet容器会自动使用线程池等技术来支持系统的运行

    在Serlet中避免使用实例变量是保证Servlet线程安全的最佳选择。从Java 内存模型也可以知道,方法中的临时变量是在栈上分配空间,而且每个线程都有自己私有的栈空间,所以它们不会影响线程的安全。

    Servlet的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写Servlet程序时要特别注意。线程安全问题主要是由实例变量造成的,因此在Servlet中应避免使用实例变量。如果应用程序设计无法避免使用实例变量,那么使用同步来保护要使用的实例变量,但为保证系统的最佳性能,应该同步可用性最小的代码路径。

    线程安全和不安全的变量:

    1、静态变量:线程非安全。

    静态变量即类变量,位于方法区,为所有对象共享,共享一份内存,一旦静态变量被修改,其他对象均对修改可见,故线程非安全。

    2、实例变量:单例模式(只有一个对象实例存在)线程非安全,非单例线程安全。

    实例变量为对象实例私有,在虚拟机的堆中分配,若在系统中只存在一个此对象的实例,在多线程环境下,“犹如”静态变量那样,被某个线程修改后,其他线程对修改均可见,故线程非安全;如果每个线程执行都是在不同的对象中,那对象与对象之间的实例变量的修改将互不影响,故线程安全。

    3、局部变量:线程安全。

    每个线程执行时将会把局部变量放在各自栈帧的工作内存中,线程间不共享,故不存在线程安全问题。

    参考博文:

    展开全文
  • 需求是这样:如从文件中读取了10条数据,将数据参数循环给post请求,然后分别记录每个请求所用时间,最后记录平均请求时间,希望能从原有代码上使用多线程处理。请求和响应。 原有代码: //读取excel ds = ...
  • SpringBoot--多线程处理

    千次阅读 2021-07-31 00:38:02
    原文网址:SpringBoot--多线程处理_IT利刃出鞘的博客-CSDN博客 简介 为什么需要多线程 项目里经常会遇到这样的场景: 读一次数据库的某个表 遍历这些数据,对每一个数据,都以它为条件再次查其他表 将第二步查到的...

    原文网址:SpringBoot--多线程处理_IT利刃出鞘的博客-CSDN博客

    简介

    为什么需要多线程

    项目里经常会遇到这样的场景:

    1. 读一次数据库的某个表
    2. 遍历这些数据,对每一个数据,都以它为条件再次查其他表
    3. 将第二步查到的数据组合起来,返回给前端

            那么问题来了,数据量大了之后,会很费时间,而且在循环里边操作数据库是非常低效的。这点也在《阿里巴巴Java开发规范手册》里边:“循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、 获取数据库连接,进行不必要的 try-catch 操作(这个 try-catch 是否可以移至循环体外)。”。

            如果业务需求就只能在循环里操作数据库,那么最好的解决方法就是使用多线程处理,本文介绍如何处理。

    实际场景

    需求

    假设有一个接口,获得所有订单的信息,按创建时间由近到远排序。

    数据库表结构

    • 订单表的字段:订单id、用户id、总金额、商品id、商品的数量、创建时间 等。
    • 用户表的字段:用户id、用户名字、用户的电话、注册时间 等。
    • 商品表的字段:商品id、商品名字 等。

    业务流程

    1. 读出订单表前n行数据
    2. 用第1步的每个数据的用户id去用户表获取用户的信息
    3. 将第2步获取到的用户信息整合到订单VO里。

    说明

    本处为了简单,用这种方法处理:

    1. 仅获取订单的id、用户id、用户名字。
    2. 使用模拟数据,不实际操作数据库。用sleep()模拟对数据库的操作。
    3. 所有代码都在controller层处理。(实际业务中肯定要放到service中处理)。

    思路

    整体方案

    1. 多线程方案:使用线程池。
    2. 等待多线程执行完毕的方案:CoutDownLatch。
      见:JUC--CountDownLatch_IT利刃出鞘的博客-CSDN博客
    3. 如何排序:
      1. 方案1:所有线程处理完之后统一排序。(此法简单,本文使用此方法)
      2. 方案2:使用队列,前边的线程将结果放入最终结果集后,唤醒下一个线程将结果放入结果集。(较为复杂)。
        见:队列_IT利刃出鞘的博客-CSDN博客(搜索:“顺序消费实例”)

    细节

    1. 线程池的核心线程数、最大线程数如何设置。
      1. 见:线程池--综述_IT利刃出鞘的博客-CSDN博客  搜索:“线程池个数设置”
    2. 线程安全的List。
      1. 见:Java类集--List--线程安全_IT利刃出鞘的博客-CSDN博客

    代码

    公共代码

    controller

    package com.example.order.controller;
    
    import com.example.order.entity.OrderVO;
    import com.example.order.entity.User;
    import com.example.order.task.OrderTask;
    import com.example.order.task.OrderTask2;
    import com.example.utils.SynchroniseUtil;
    import com.example.utils.ThreadPoolExecutors;
    import com.example.utils.ThreadPoolExecutors2;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.PostConstruct;
    import java.time.LocalDateTime;
    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    import java.util.stream.Collectors;
    
    @RestController
    @RequestMapping
    public class OrderController {
        private List<OrderVO> orderVOS = new ArrayList<>();
        private List<User> users = new ArrayList<>();
    
        //初始化时就创建好数据。模拟数据库已经存在的数据
        @PostConstruct
        public void createData() {
            long dataCount = 500;
    
            // 创建订单数据。模拟已经插入到数据库的订单
            for (long i = 0; i < dataCount; i++) {
                OrderVO orderVO = new OrderVO();
                orderVO.setId(i + 1);
                orderVO.setUserId(i + 1);
                //防止电脑太快,导致都是同一个时间,所以加一个数
                orderVO.setCreateTime(LocalDateTime.now().plusSeconds(i));
                orderVOS.add(orderVO);
            }
    
            // 创建用户数据。模拟已经插入到数据库的用户
            for (long i = 0; i < dataCount; i++) {
                User user = new User();
                user.setId(i + 1);
                user.setUserName("用户名" + (i + 1));
                users.add(user);
            }
            orderVOS = orderVOS.stream()
                .sorted(Comparator.comparing(OrderVO::getCreateTime).reversed())
                .collect(Collectors.toList());
        }
    
        @GetMapping("/getOrderDetails")
        public List<OrderVO> getOrderDetails() {
            long startTime = System.currentTimeMillis();
    
            List<OrderVO> orderVOList;
    
            //这里是不同的执行方式(单线程/线程池)
    
            long endTime = System.currentTimeMillis();
    
            System.out.println("执行时间:" + (endTime - startTime) + " ms");
            return orderVOList;
        }
    }

    entity

    订单 

    package com.example.order.entity;
    
    import lombok.Data;
    
    import java.time.LocalDateTime;
    
    @Data
    public class Order {
        private Long id;
        private Long userId;
        private LocalDateTime createTime;
    }
    

    订单视图(用于返回数据)

    package com.example.order.entity;
    
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    
    @Data
    @EqualsAndHashCode(callSuper = true)
    public class OrderVO extends Order{
        private String userName;
    }
    

    用户

    package com.example.order.entity;
    
    import lombok.Data;
    
    @Data
    public class User {
        private Long id;
        private String userName;
    }
    

    方案1:单线程

    代码

    package com.example.order.controller;
    
    import com.example.order.entity.OrderVO;
    import com.example.order.entity.User;
    import com.example.order.task.OrderTask;
    import com.example.order.task.OrderTask2;
    import com.example.utils.SynchroniseUtil;
    import com.example.utils.ThreadPoolExecutors;
    import com.example.utils.ThreadPoolExecutors2;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.PostConstruct;
    import java.time.LocalDateTime;
    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    import java.util.stream.Collectors;
    
    @RestController
    @RequestMapping
    public class OrderController {
        private List<OrderVO> orderVOS = new ArrayList<>();
        private List<User> users = new ArrayList<>();
    
        //初始化时就创建好数据。模拟数据库已经存在的数据
        @PostConstruct
        public void createData() {
            long dataCount = 500;
    
            // 创建订单数据。模拟已经插入到数据库的订单
            for (long i = 0; i < dataCount; i++) {
                OrderVO orderVO = new OrderVO();
                orderVO.setId(i + 1);
                orderVO.setUserId(i + 1);
                //防止电脑太快,导致都是同一个时间,所以加一个数
                orderVO.setCreateTime(LocalDateTime.now().plusSeconds(i));
                orderVOS.add(orderVO);
            }
    
            // 创建用户数据。模拟已经插入到数据库的用户
            for (long i = 0; i < dataCount; i++) {
                User user = new User();
                user.setId(i + 1);
                user.setUserName("用户名" + (i + 1));
                users.add(user);
            }
            orderVOS = orderVOS.stream()
                    .sorted(Comparator.comparing(OrderVO::getCreateTime).reversed())
                    .collect(Collectors.toList());
        }
    
        @GetMapping("/getOrderDetails")
        public List<OrderVO> getOrderDetails() {
            long startTime = System.currentTimeMillis();
    
            List<OrderVO> orderVOList;
            orderVOList = singleThread(orderVOS);
    
            long endTime = System.currentTimeMillis();
    
            System.out.println("执行时间:" + (endTime - startTime) + " ms");
            return orderVOList;
        }
    
        private List<OrderVO> singleThread(List<OrderVO> orders) {
            List<OrderVO> result = new ArrayList<>(orders);
            for (OrderVO orderVO : result) {
                //模拟从数据库里查数据
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for (User user : users) {
                    if (orderVO.getUserId().equals(user.getId())) {
                        orderVO.setUserName(user.getUserName());
                        break;
                    }
                }
            }
            return result;
        }
    }

    测试

    请求:http://localhost:8080/getOrderDetails

    后端打印

    执行时间:7525 ms

    前端结果:

    总结

    缺点

    1. 才500个数据,就用了7秒多,实在太慢。

    方案2:线程池(每个数据一个任务)

    简介

    上边已经看到了,单线程特别慢,本处使用线程池来优化:每个数据一个任务。

    controller

    package com.example.order.controller;
    
    import com.example.order.entity.OrderVO;
    import com.example.order.entity.User;
    import com.example.order.task.OrderTask;
    import com.example.order.task.OrderTask2;
    import com.example.utils.SynchroniseUtil;
    import com.example.utils.ThreadPoolExecutors;
    import com.example.utils.ThreadPoolExecutors2;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.PostConstruct;
    import java.time.LocalDateTime;
    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    import java.util.stream.Collectors;
    
    @RestController
    @RequestMapping
    public class OrderController {
        private List<OrderVO> orderVOS = new ArrayList<>();
        private List<User> users = new ArrayList<>();
    
        //初始化时就创建好数据。模拟数据库已经存在的数据
        @PostConstruct
        public void createData() {
            long dataCount = 500;
    
            // 创建订单数据。模拟已经插入到数据库的订单
            for (long i = 0; i < dataCount; i++) {
                OrderVO orderVO = new OrderVO();
                orderVO.setId(i + 1);
                orderVO.setUserId(i + 1);
                //防止电脑太快,导致都是同一个时间,所以加一个数
                orderVO.setCreateTime(LocalDateTime.now().plusSeconds(i));
                orderVOS.add(orderVO);
            }
    
            // 创建用户数据。模拟已经插入到数据库的用户
            for (long i = 0; i < dataCount; i++) {
                User user = new User();
                user.setId(i + 1);
                user.setUserName("用户名" + (i + 1));
                users.add(user);
            }
            orderVOS = orderVOS.stream()
                    .sorted(Comparator.comparing(OrderVO::getCreateTime).reversed())
                    .collect(Collectors.toList());
        }
    
        @GetMapping("/getOrderDetails")
        public List<OrderVO> getOrderDetails() throws Exception{
            long startTime = System.currentTimeMillis();
    
            List<OrderVO> orderVOList;
            orderVOList = multiThread(orderVOS);
    
            long endTime = System.currentTimeMillis();
    
            System.out.println("执行时间:" + (endTime - startTime) + " ms");
            return orderVOList;
        }
    
        private List<OrderVO> multiThread(List<OrderVO> orders) throws Exception{
            ExecutorService executor = ThreadPoolExecutors.getSingletonExecutor();
            SynchroniseUtil<OrderVO> synchroniseUtil = new SynchroniseUtil<>(orders.size());
            System.out.println("任务个数:" + orders.size());
    
            for (OrderVO order : orders) {
                OrderTask orderTask = new OrderTask(order, users, synchroniseUtil);
                executor.execute(orderTask);
            }
    
            List<OrderVO> list = null;
            try {
                list = synchroniseUtil.get(10, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            if (list != null) {
                list = list.stream()
                        .sorted(Comparator.comparing(OrderVO::getCreateTime).reversed())
                        .collect(Collectors.toList());
            }
    
            return list;
        }
    }

    自定义Task

    package com.example.order.task;
    
    import com.example.order.entity.OrderVO;
    import com.example.order.entity.User;
    import com.example.utils.SynchroniseUtil;
    
    import java.util.List;
    
    public class OrderTask implements Runnable {
        private OrderVO orderVO;
        private List<User> users;
        private SynchroniseUtil<OrderVO> synchroniseUtil;
    
        public OrderTask(OrderVO orderVO, 
                         List<User> users, 
                         SynchroniseUtil<OrderVO> synchroniseUtil) {
            this.orderVO = orderVO;
            this.users = users;
            this.synchroniseUtil = synchroniseUtil;
        }
    
        @Override
        public void run() {
            //模拟从数据库里查数据
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (User user : users) {
                if (orderVO.getUserId().equals(user.getId())) {
                    orderVO.setUserName(user.getUserName());
                    break;
                }
            }
            synchroniseUtil.addResult(orderVO);
        }
    }

    单例模式的线程池

    package com.example.utils;
    
    import java.util.concurrent.*;
    
    public class ThreadPoolExecutors {
        private static final int processorNumber = 
                Runtime.getRuntime().availableProcessors();
    
        private static class ThreadPoolExecutorsHolder {
            private static final ExecutorService EXECUTOR = 
                    Executors.newFixedThreadPool(processorNumber);
        }
    
        private ThreadPoolExecutors() {
        }
    
        public static ExecutorService getSingletonExecutor() {
            System.out.println("处理器数量:" + processorNumber);
            return ThreadPoolExecutorsHolder.EXECUTOR;
        }
    
    }
    

    封装CoutDownLatch

    package com.example.utils;
     
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.TimeUnit;
     
    public class SynchroniseUtil<T>{
        private CountDownLatch countDownLatch;
    
        private final List<T> result = Collections.synchronizedList(new ArrayList<>());
    
        public SynchroniseUtil(int count) {
            this.countDownLatch = new CountDownLatch(count);
        }
     
        public List<T> get() throws InterruptedException{
            countDownLatch.await();
            return this.result;
        }
     
        public List<T> get(long timeout, TimeUnit timeUnit) throws Exception{
            if (countDownLatch.await(timeout, timeUnit)) {
                return this.result;
            } else {
                throw new RuntimeException("超时");
            }
        }
     
        public void addResult(T resultMember) {
            result.add(resultMember);
            countDownLatch.countDown();
        }
    
        public void addResult(List<T> resultMembers) {
            result.addAll(resultMembers);
            countDownLatch.countDown();
        }
    }

    测试

    访问:http://localhost:8080/getOrderDetails

    后端结果

    处理器数量:25
    任务个数:500
    执行时间:301 ms

    前端结果

    总结

    优点

    1. 比单线程快很多。

    缺点

    1. 固定线程池大小的线程池,队列长度是整型数的最大值,若数据很多,每个数据一个任务,会把内存耗尽。

    方案3:线程池(多个数据一个任务)

    简介

    上边每个数据一个任务是不合适的,本处进行优化:多个数据一个任务。

    controller

    package com.example.order.controller;
    
    import com.example.order.entity.OrderVO;
    import com.example.order.entity.User;
    import com.example.order.task.OrderTask;
    import com.example.utils.SynchroniseUtil;
    import com.example.utils.ThreadPoolExecutors;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.PostConstruct;
    import java.time.LocalDateTime;
    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    import java.util.stream.Collectors;
    
    @RestController
    @RequestMapping
    public class OrderController {
        private List<OrderVO> orderVOS = new ArrayList<>();
        private List<User> users = new ArrayList<>();
    
        //初始化时就创建好数据。模拟数据库已经存在的数据
        @PostConstruct
        public void createData() {
            long dataCount = 500;
    
            // 创建订单数据。模拟已经插入到数据库的订单
            for (long i = 0; i < dataCount; i++) {
                OrderVO orderVO = new OrderVO();
                orderVO.setId(i + 1);
                orderVO.setUserId(i + 1);
                //防止电脑太快,导致都是同一个时间,所以加一个数
                orderVO.setCreateTime(LocalDateTime.now().plusSeconds(i));
                orderVOS.add(orderVO);
            }
    
            // 创建用户数据。模拟已经插入到数据库的用户
            for (long i = 0; i < dataCount; i++) {
                User user = new User();
                user.setId(i + 1);
                user.setUserName("用户名" + (i + 1));
                users.add(user);
            }
            orderVOS = orderVOS.stream()
                    .sorted(Comparator.comparing(OrderVO::getCreateTime).reversed())
                    .collect(Collectors.toList());
        }
    
        @GetMapping("/getOrderDetails")
        public List<OrderVO> getOrderDetails() throws Exception{
            long startTime = System.currentTimeMillis();
    
            List<OrderVO> orderVOList;
            orderVOList = multiThread(orderVOS);
    
            long endTime = System.currentTimeMillis();
    
            System.out.println("执行时间:" + (endTime - startTime) + " ms");
            return orderVOList;
        }
    
        private List<OrderVO> multiThread(List<OrderVO> orders) throws Exception{
            ThreadPoolExecutor executor = ThreadPoolExecutors.getSingletonExecutor();
            int unitLength = orders.size() / ThreadPoolExecutors.getQueueSize() + 1;
            int synchroniseCount = orders.size() / unitLength;
            synchroniseCount = orders.size() % unitLength == 0 
                                    ? synchroniseCount : synchroniseCount + 1;
            SynchroniseUtil<OrderVO> synchroniseUtil = new SynchroniseUtil<>(synchroniseCount);
            System.out.println("任务个数:" + synchroniseCount);
    
            for (int i = 0; i < orders.size(); i += unitLength) {
                int toIndex = Math.min(i + unitLength, orders.size() - 1);
                List<OrderVO> orderVOSubList = orders.subList(i, toIndex);
                OrderTask orderTask = new OrderTask(orderVOSubList, users, synchroniseUtil);
                executor.execute(orderTask);
            }
    
            List<OrderVO> list = null;
            try {
                list = synchroniseUtil.get(10, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
                return null;
            }
    
            if (list != null) {
                list = list.stream()
                        .sorted(Comparator.comparing(OrderVO::getCreateTime).reversed())
                        .collect(Collectors.toList());
            }
    
            return list;
        }
    
    }

    自定义Task

    package com.example.order.task;
    
    import com.example.order.entity.OrderVO;
    import com.example.order.entity.User;
    import com.example.utils.SynchroniseUtil;
    
    import java.util.List;
    
    public class OrderTask implements Runnable {
        private List<OrderVO> orderVOS;
        private List<User> users;
        private SynchroniseUtil<OrderVO> synchroniseUtil;
    
        public OrderTask(List<OrderVO> orderVOS,
                          List<User> users,
                          SynchroniseUtil<OrderVO> synchroniseUtil) {
            this.orderVOS = orderVOS;
            this.users = users;
            this.synchroniseUtil = synchroniseUtil;
        }
    
        @Override
        public void run() {
            //模拟从数据库里查数据
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            for (OrderVO orderVO : orderVOS) {
                for (User user : users) {
                    if (orderVO.getUserId().equals(user.getId())) {
                        orderVO.setUserName(user.getUserName());
                        break;
                    }
                }
            }
    
            synchroniseUtil.addResult(orderVOS);
        }
    }

    单例的线程池(指定队列长度)

    package com.example.utils;
    
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class ThreadPoolExecutors {
        private static final int processorNumber =
                Runtime.getRuntime().availableProcessors();
        private static final int corePoolSize = processorNumber;
        private static final int maximumPoolSize = processorNumber * 2 + 1;
        private static final int queueSize = 100;
    
        private static class ThreadPoolExecutorsHolder {
            private static final ThreadPoolExecutor INSTANCE =
                    new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
                    200,TimeUnit.MILLISECONDS,
                    new LinkedBlockingDeque<>(queueSize));
        }
    
        private ThreadPoolExecutors() {
        }
    
        public static ThreadPoolExecutor getSingletonExecutor() {
            System.out.println("处理器数量:" + processorNumber);
    
            return ThreadPoolExecutorsHolder.INSTANCE;
        }
    
        public static int getQueueSize() {
            return queueSize;
        }
    }
    

    封装CountDownLatch

    package com.example.utils;
     
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.TimeUnit;
     
    public class SynchroniseUtil<T>{
        private CountDownLatch countDownLatch;
    
        private final List<T> result = Collections.synchronizedList(new ArrayList<>());
    
        public SynchroniseUtil(int count) {
            this.countDownLatch = new CountDownLatch(count);
        }
     
        public List<T> get() throws InterruptedException{
            countDownLatch.await();
            return this.result;
        }
     
        public List<T> get(long timeout, TimeUnit timeUnit) throws Exception{
            if (countDownLatch.await(timeout, timeUnit)) {
                return this.result;
            } else {
                throw new RuntimeException("超时");
            }
        }
     
        public void addResult(T resultMember) {
            result.add(resultMember);
            countDownLatch.countDown();
        }
    
        public void addResult(List<T> resultMembers) {
            result.addAll(resultMembers);
            countDownLatch.countDown();
        }
    }

    测试

    访问:http://localhost:8080/getOrderDetails

    后端结果

    处理器数量:12
    任务个数:84
    执行时间:117 ms

    前端结果

    总结

    优点

    可见,此时速度比每个数据一个任务更快。(原因待分析,猜测:任务越少,在某个调度、唤醒之类的地方耗时就少,于是速度更快)

    大量测试

    数据量单线程线程池(每个数据一个任务)线程池(多个数据一个任务)
    1001498 ms72 ms77 ms
    5007525 ms312 ms113 ms
    100015024 ms605 ms125 ms
    500075160 ms3008 ms163 ms

    总结

            可见,多个数据一个任务速度最快。

            多个数据一个任务时,随着数据成倍的增加,耗时却没有成倍增加。原因分析:与线程池一个任务包含的数据量有关系。因为我是固定死了队列的长度,然后把总数据量平均分配到每一个队列上,如果数据量成倍增加,平均到一个任务里边,就增加的很少了。

            当然,实际上任务并不是平均分到了队列里边,因为任务进来,先去占用核心线程,再去占用队列,再去占用最大线程数,见:线程池--综述_IT利刃出鞘的博客-CSDN博客(搜索:“线程池流程”)。按我本篇程序里的写法,实际队列并不会占满,而且最大线程数也没有用完。

    其他网址

    JUC--CountDownLatch_IT利刃出鞘的博客-CSDN博客
    线程池--综述_IT利刃出鞘的博客-CSDN博客
    List--线程安全_IT利刃出鞘的博客-CSDN博客

    展开全文
  • 多线程应用(一)—Http请求阻塞回调处理1.需求描述1.1场景说明:由于,微信端的业务需求量越来越大.将业务与微信第三方事件处理耦合在一起的单一项目的结构已经逐渐暴露出,承载能力不足的缺点.所以,需要将与微信的交互...
  • 使用多线程往List添加数据

    万次阅读 2020-05-15 14:43:17
    我们在日常写代码的过程中,经常会使用多线程提高效率,我们在使用多线程过程中难免会出现往List集合修改数据。 下面我们来尝试一下往ArrayList 添加数据: public static void main(String[] args) { List<...
  • 1、多线程工具TreadTestHttp package com; import java.util.concurrent.CountDownLatch; public class TreadTestHttp { public static void main(String[] args) throws InterruptedException { Runn...
  • httpclient 多线程高并发Get请求

    万次阅读 2016-10-21 19:06:10
    为了达到较高的效率,优化了下httpclient(版本:4.2.3)的get请求,具体的就是使用http的连接池,这样不需要每次get都需要3次握手,大大提高了并发能力,并且失败率降低了100倍,具体代码如下: public class...
  • springboot线程池拉取数据 多线程

    千次阅读 多人点赞 2022-04-09 03:26:26
    springboot线程池完成数据拉取,欢迎评论
  • django自带Gateway组件(类似Gunicorn 或者 uWSGI)实现并发处理多请求,runserver 默认是单进程多线程。 django-admin and manage.py:The development server is multithreaded by default. Use the --noth...
  • //多线程调用注意配置,根据线程数设定 cm.setDefaultMaxPerRoute(300); requestConfig = RequestConfig.custom() //数据传输过程中数据包之间间隔的最大时间 .setSocketTimeout(20000) //连接建立时间,三次握手...
  • 实现PHP多线程异步请求的3种方法

    千次阅读 2016-03-04 10:01:52
    CURL扩展是我们在开发过程中最常用的一种方法,他是一个强大的HTTP命令行工具,可以模拟POST/GET等HTTP请求,然后得到和提取数据,显示在"标准输出"(stdout)上面。 $cl = curl_init(); $curl_opt = array...
  • 探究django能否通过线程返回http请求

    千次阅读 2017-08-19 15:01:00
    我的django版本: 1.11.2 首先说两点知识: 1. django在1.7版本之后服务默认是多线程的,也可以在...由于某些需求,多线程服务情况下,本来我想,来一个请求便自己开一个线程去取数据,然后通过这个线程响应这个请...
  • Java多线程学习(吐血超详细总结)

    万次阅读 多人点赞 2015-03-14 13:13:17
    本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。
  • 1、场景:有1万家机构需要初始化全文检索,...4、设置HTTP Request,(这里直接在请求里配置了具体请求参数值,所以无须配置Http请求默认值)--》 5、查看结果树==》 6、聚合报告 7、CSV文件 完整的...
  • HTTP】进程与线程

    千次阅读 2022-03-24 20:24:29
    浏览器:多线程的进程 2、两者关系 进程中某个线程执行出错导致整个进程崩溃; 进程之间互相隔离,可通过IPC机制通信; 进程所占资源在其关闭后被操作系统回收,即使某个线程产生内存泄漏,进程退出时相关内存资源...
  • 模拟高并发的原理就是:利用线程池去执行线程通过httpclient访问controller  package com.xtzn.utils; import com.alibaba.fastjson.JSONObject; import org.apache.http.client.config.RequestConfig; ...
  • 线程线程数可理解为用户数。 Ramp-up时间可理解为所有线程(用户)在该时间段内将请求发送完。...HTTP请求 例如我们当前所要测的域名为https://www.qq.com/ 协议:填http或https。http可兼容https的情况,
  • 多线程的优缺点

    千次阅读 2019-06-17 15:51:49
    最近手上拿到一个程序,其中是一个视频监控的小程序,其中调用了线程,但是调试的时候出现的BUG,调试了N久,无果。最后,我把线程函数用一个普通的函数替代了,就没有错误了,后来,变思索,此处为何要用线程,不用...
  • python爬虫之多线程、多进程爬虫

    万次阅读 多人点赞 2019-05-09 17:22:00
    多线程对爬虫的效率提高是非凡的,当我们使用python的多线程有几点是需要我们知道的: 1.Python的多线程并不如java的多线程,其差异在于当python解释器开始执行任务时,受制于GIL(全局解释所),Python 的线程被限制...
  • 线程是共享cpu的,那么多线程比单线程,能提升处理速度吗? 好比,一个窗口(一个cpu),三个人来办理业务。单线程:一个办完一个办。多线程:大家轮着办,我一会给你办,你会儿给他办。 但是单线程,..
  • 前5篇博文完成了此框架的一大模块—–多线程下载,而这两篇文章实现另一大模块——Http基本框架封装,在上一篇博文中完成了HttpHeader的接口定义和实现、状态码定义及response、request接口封装和实现,定义了许多...
  • 在原先的理解中,每一次接口请求都会发起一个新的线程..但是发现不是这么回事儿.. 在测试中..判断当前线程的名称是否为空, 为空时将当前请求的地址赋值给线程名称..不为空的话进断点查看. 结果是: 第一次...
  • 昨天操作WebAPI的时候由于涉及到主线程(UI线程)与子线程之间的通信时采用Thread创建子线程,并复写 public void run()方法时,因为run()方法的返回值 类型是void的,所以操作无法把执行完成之后的数据返回给...
  • 如题,这种情况一般在数字类数据更新时需要保证万无一失,尤其是金额类的数字 比如小明的银行号有1000块钱 他做了一笔交易20元,很简单,我们要做一次更新 UPDATE XXX SET MONEY=NOWMONEY-20 W...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 378,703
精华内容 151,481
关键字:

多线程http请求数据