【问题标题】:How to implement executor service by passing new thread as parameter to execute?如何通过传递新线程作为参数来执行执行器服务?
【发布时间】:2021-04-20 16:20:28
【问题描述】:

我需要重构代码以查看它是否可以帮助我解决“无法打开 Hibernate Session 进行事务”。我目前正在尝试简化代码中处理线程的方式。

现有代码如下所示。让我们称之为“代码 A”:

    if (!CollectionUtils.isEmpty(dailyReportProjectList)) {
            for (ProjectEntity project : dailyReportProjectList) {
                Thread.sleep(2000);
                new Thread(() -> {
                    try {
                        // Implementation Logic

                        if (isConfig == true) {
                            // Generating Daily Report
                        
                            if (dailyRep != null) {
                                LOG.info(
                                        "============start of daily report mail for zone : " + zone + ", newZone : "
                                                + newZone + " for date : " + currOrPrevDay + "===============");
                                new Thread(() -> {
                                    try {
                                        //genericController;
                                        
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                        
                                        }
                                    }
                                }).start();
                            }
                        } else {
                                 //"All 4 default reports for site : " + project.getId() + ", empId:" + project.getEmployerId());
                            
                                }
                            }
                        }
                        LOG.info("End of generateReportByZone >> zone : " + zone);
                    } catch (Exception e2) {
                        e2.printStackTrace();
                        }
                    }
                }).start();
            }
        }
        

为了简化这一点,我决定继续使用 Executor Service。我提到了一些例子,我对使用 service.submit() 或 service.execute() 感到困惑。 我没有从下面的代码中看到我想要的好处。你能帮我找出这个方法的任何问题吗?

编辑:基于 cmets,我已经简化了上面的现有代码。线程内部有一个线程,我觉得没有太大的成就。有这样的实现可以吗?

我打算做以下事情:

  1. 不要传递线程,而是作为 for 循环中的参数,创建一个单独的类并让它实现可运行。

      public class ReportProcessor implements Runnable {
      private int id;
      public ReportProcessor (int id){
       this.id = id;
       }
    
       public void run(){
       try {
      String currOrPrevDay = new String();
      ...// write the code in the try element of 'code A' here onwards
    
  2. 在“代码 A”执行程序中。提交新创建的类

                 for (i = 0; i < dailyReportProjectList.length; i ++){
             service.submit(new ReportProcessor(i));
    
             }
    

但是,如果我将逻辑分离到一个新类中,我如何满足现有规定的“代码 A”所需的依赖关系。我正在尝试在本教程https://www.youtube.com/watch?v=KUdro0G1BV4&t=325s

的基础上为我的执行器服务建模

【问题讨论】:

  • 您的帖子太大且难以阅读。首先用几个更简单、更有意义的调用重构这个怪物。
  • 嗨,marc,我肯定会尝试这样做,但您能否帮助我确认以这种方式调用线程是正确的。如果需要,我将使用虚拟值简化代码。
  • 将示例代码精简到解决您的特定技术问题所需的绝对最低限度。 MCVE
  • 永远不要将线程传递给这样的执行程序。传入的线程被视为可运行的,实际的操作系统线程未被使用。这是在浪费资源。
  • 执行器服务的全部意义在于它会根据需要为您创建线程。相反,您应该将可调用对象或可运行对象传递给执行程序。

标签: java multithreading threadpool executorservice


【解决方案1】:

不要传递线程、传递 lambda 或任何“可运行”的东西。

        ExecutorService service = Executors.newFixedThreadPool(3);

        for (int i = 0; i < 10; i++) {
            final int number = i;
            service.execute(() -> System.out.println("test" + number));
        }

编辑:
我真的认为这段代码需要简单。您似乎想创建报告。
那么为什么要在一个线程中创建一个线程呢?
为什么 Thread.sleep ? (通常是渎职,更喜欢等待/通知)

我真的认为你根本不需要线程。
但如果你真的想要(或需要)它们,松耦合:

  • 每个线程都执行一个精确的任务。
  • 决定做什么的测试必须在上游。

并尝试流和功能接口。它将简化您的代码。

dailyReportProjectList.parallelStream()
    .filter(condition)
    .forEach(doSomething)

流自己管理线程。

【讨论】:

  • 嗨,马克,根据您的输入,我正在尝试进行更改,并在我的问题中进行了编辑。可以参考一下吗。
猜你喜欢
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多