在自己编写的方法里面开启多线程,线程内的值怎么正常传递给自己方法内的变量

啵溜啵溜neal 发布于 2019/07/17 16:15
阅读 766
收藏 0

        在我自己方法里面调用多线程,线程内赋值给外面会很不确定,因为系统始终快于子线程,所以会在我自己方法先运行到最后才会执行子线程内的方法,导致没有赋值上.如果让程序睡眠一些时间的话,可以取到值,但是这个时间不确定,所以也不可取.

       求大神帮忙看看,代码如下:

@ResponseBody
   @RequestMapping("/upload")
   public Map<String, Object> upload(@RequestParam(value = "path", required = false) String path,
                             @RequestParam(value = "dns1", required = false) String dns1,
                             @RequestParam(value = "dns2", required = false) String dns2,
           HttpServletResponse response,HttpServletRequest  request)throws Exception {
      Map<String, Object> map = new HashMap<String, Object>();
      
      String webPath=request.getServletContext().getRealPath("");
      //读取TXT文件里面的域名信息
      List<String> importTxt = TextUtils.importTxt(new File(webPath + path));
      Dns dns = new Dns();
      List<Dns> original_datas = new ArrayList<>();//dns1数据
      List<Dns> this_datas = new ArrayList<>();//dns2数据
      ExecutorService pool = Executors.newFixedThreadPool(10);
      for (String domain : importTxt) {
         if (domain == null || domain.isEmpty()) {
            continue;
         } else {
            //解析两份数据
//          original_datas.addAll(DnsUtils.getIps(domain, dns1));
//          this_datas.addAll(DnsUtils.getIps(domain, dns2));

            Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
               try {
                  original_datas.addAll(DnsUtils.getIps(domain, dns1));
                  System.out.println(Thread.currentThread().getName()+"  original_datas");
               } catch (IOException | InterruptedException e) {
                  e.printStackTrace();
               }
            }
         });

         /*Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
               try {
                  this_datas.addAll(DnsUtils.getIps(domain, dns2));
                  System.out.println(Thread.currentThread().getName()+"  this_datas");
               } catch (IOException | InterruptedException e) {
                  e.printStackTrace();
               }
            }
         });*/
            pool.execute(thread1);
            //pool.execute(thread2);
            this_datas.addAll(DnsUtils.getIps(domain, dns2));
         }
      }
      pool.shutdown();
      //Thread.sleep(10000);
      System.out.println("original_datas="+original_datas.toString());
      System.out.println("this_datas="+this_datas.toString());
      //数据对比
      List<String> dnsDuibi = MyUtil.dnsDuibi(original_datas,this_datas);

        dnsService.addList(original_datas);
        dnsService.addList(this_datas);

        map.put("msg", "上传成功");
      map.put("success", true);
      //map.clear();
      //  原数据比  this_data
      map.put("original_datas", original_datas);
      map.put("this_datas", this_datas);
      map.put("dnsDuibi", dnsDuibi);
      return map;
   }

因为我需要用多线程执行的是两行代码,如果用一个子线程去执行其中一条,另一条不用多线程,似乎可行,但是效率还是很低,也会遇到同步的问题.麻烦大神指点下

加载中
0
定期马甲
定期马甲

管道pipe 通信 

线程写 pipe.write(dns)

主线程 读取 pipe.read() 没有数据到达前是阻塞的一直等待

isscy
isscy
不太懂 能详细教教吗
0
uglybaby
uglybaby

Future?CountDownLatch?

啵溜啵溜neal
啵溜啵溜neal
感谢大佬
0
isscy
isscy

无非是效率低点 为什么会遇到同步的麻烦

啵溜啵溜neal
啵溜啵溜neal
就是阻塞,主线程总会先于子线程之前执行
0
两江总督是码农
两江总督是码农

我这边模拟了你的那个相似场景,大概的伪代码,你看看

 

//产生数据工具类

 

 

//线程工具类

 

//controller层代码

 

public class TestController {

    private static ExecutorService executorService = Executors.newFixedThreadPool(2);
    private static CountDownLatch latch = new CountDownLatch(2);
    @RequestMapping(value = "/test")
    public Object test(@RequestParam(value = "dns") String dns) throws InterruptedException {
        String readStr = "str";
        List<Object> original_datas = new ArrayList<>();//dns1数据
        List<Object> this_datas = new ArrayList<>();//dns2数据
        List<Map> result = new ArrayList<>();
        Task original_datas_thread = new Task(readStr, dns);
        Task this_datas_thread = new Task(readStr, dns);
        List<Task> taskList = new ArrayList<>();
        taskList.add(original_datas_thread);
        taskList.add(this_datas_thread);
        taskList.forEach(item -> {
            Future<Map> submit = executorService.submit(item);
            try {
                result.add(submit.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            latch.countDown();
        });
        latch.await();
        executorService.shutdown();
        original_datas = (List<Object>) result.get(0).get("str");
        this_datas = (List<Object>) result.get(1).get("str");
        System.out.println("原始数据量:" + original_datas.size());
        System.out.println("当前数据量:" + this_datas.size());
        return "OK";

 

结果:

 

 

 

啵溜啵溜neal
啵溜啵溜neal
回复 @两江总督是码农 : 速度慢不全是在读取方面,我这个代码是批量操作命令行获取结果,因为命令行里面有些数据确实需要一些时间相应,我这边控制不了的.所以我希望能够同时去执行一批命令,共同返回我需要的数据,来减少等待的时间,但是目前这样似乎不行
两江总督是码农
两江总督是码农
回复 @啵溜啵溜neal : 数据量很大的话,多思考思考有没有其他的方法读取加入
啵溜啵溜neal
啵溜啵溜neal
感谢大佬,目前这个问题我用CountDownLatch已经解决,但是貌似我多线程并没有提高效率,执行少量数据还是很要很久. 我要进行多线程操作的就是这两条代码: original_datas.addAll(DnsUtils.getIps(domain, dns1)); this_datas.addAll(DnsUtils.getIps(domain, dns2));
0
小99
小99
搜索一下spring AsyncResult
啵溜啵溜neal
啵溜啵溜neal
感谢
0
Areya
Areya

Future或者CountDownLatch进行阻塞吧,这里的逻辑必须等待。

啵溜啵溜neal
啵溜啵溜neal
感谢,这个我知道了,但是貌似我这样写的多线程并没有提升我代码的效率,惆怅
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部