qq_38291548 2020-04-20 17:09 采纳率: 50%
浏览 165
已采纳

并行访问接口流被关闭

res: (respnse) => {
              console.info(respnse.result.active)
              let url = respnse.result.active == 'dev'
                ?'http://10.68.105.145:8081/sxhblh-boot/trainmanage/trainInfo/visitImg?imgName=' + respnse.result.url
                :'http://ctg.com.cn:8081/sxhblh-boot/trainmanage/trainInfo/visitImg?imgName=' + respnse.result.url
              return url
            },
    @GetMapping("visitImg")
@ResponseBody
public synchronized void visitImg(String imgName,HttpServletResponse response){
    String path;
    InputStream inputStream = null;
    BufferedInputStream bufferedInputStream = null;
    BufferedOutputStream bufferedOutputStream = null;
    try {
        path = "img";
        inputStream = FtpClientUtil.readFile(imgName,path);
        bufferedInputStream = new BufferedInputStream(inputStream);

        bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
        byte[] buf = new byte[1024 * 1024];
        int length = 0;
        while ((length = bufferedInputStream.read(buf)) != -1) {
            bufferedOutputStream.write(buf, 0, length);
            bufferedOutputStream.flush();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            inputStream.close();
            bufferedInputStream.close();
            bufferedOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

如第一段代码所示,这是上传图片后的回调,给图片设置src,可以看到,所有的图片访问调用的都是同一个接口visitImg,参数为imgName,现在的问题是,上传多个图片后,始终只能显示第一个图片,后面的图片都无法显示,后台报错stream closed流关闭,但是我打了断点之后,会进多次断点,并且图片都能显示,然后我在想是不是打了断点之后,上一次请求阻塞下一次请求,使得本来所有图片的访问从并行变为了串行,由此思考我想到了一个解决办法,给方法加上锁synchronized,问题解决了。问题是解决了,但是问题的本质我还是没有弄懂,1、为什么并行访问接口会导致stream closed流被关闭,2、还有没有更好的解决办法(一开始还想在前端设置请求队列,但是请求是以src的形式,所以放弃了),还请各位大神们赐教

  • 写回答

2条回答 默认 最新

  • 毕小宝 博客专家认证 2020-04-21 09:20
    关注

    需要加上 synchronized ,是因为 Controller 类是单例,所有浏览器访问这个请求方法时,都会调用这个类的实例的。
    但 Tomcat 是开启多个线程处理浏览器请求的,所以这个类是多线程环境下,需要安全同步措施。
    如果恰好文件名称相同 FtpClientUtil 这个获取文件方法可能也存在多线程同步问题,目标对象为同一个文件的时候,可能会出现 StreamClose 这个要看异常才知道是什么流关闭。

    加上断点后后面请求被迫暂停,所以本质是是顺序的。Web 请求一般都是后台做并发控制的,synchronize 加在整个方法上,优化的话可以缩小加锁粒度,只在文件处理那段代码上加锁。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况