有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java执行器服务。execute()以静默方式退出run()方法

尝试测试我的一个类是否可以处理在多个线程上被访问的问题。我有一个JUnit测试,其中我创建了一个类来实现Runnable并运行我的类

当我运行execute时,它到达run()方法中的一行,并在该线程上退出,而不报告任何问题,我用Try-Catch(Throwable)将其包装起来,但仍然没有出现问题的迹象

这是我的密码:

class ConcurrencyTests {
    class ConcurrentComponentTracker implements Runnable {
        private String component;

        ConcurrentComponentTracker(String component) {
            this.component = component;
       }

       @Override
       public void run() {
           try {
           System.out.printf("Component to track: [%s]\n", component);
           ParserHandler parserHandler = new ParserHandler();
           System.out.println(parserHandler.componentTracker(component));
           }
           catch (Throwable t) {
               t.printStackTrace();
           }
       }
   }

    @Test
    void runRunner() {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        String[] componentsToTrack = {"x", "y", "z"};

        executor.execute(new ConcurrentComponentTracker(componentsToTrack[0]));
        executor.execute(new ConcurrentComponentTracker(componentsToTrack[1]));
        executor.execute(new ConcurrentComponentTracker(componentsToTrack[2]));
    }
}

以及输出:

Component to track: [x]

Component to track: [y]

Component to track: [z]

它似乎只是在ParserHandler实例化行上退出,而没有报告任何内容。当尝试调试并进入该行时,它只跳到最后,而不让我检查ParserHandler类实例化


共 (2) 个答案

  1. # 1 楼答案

    JUnit测试实际上应该测试和验证结果。在这种特殊情况下,测试产生的输出应该由开发人员/测试人员验证,因此这不是自动化。 我建议您使用Future<?>来跟踪任务执行的状态。对于Runnable任务get()Future<?>的方法将返回null如果任务成功执行,否则它将转发您使用ExecutionException包装的异常。代码如下所示:

    @Test
    void runRunner() {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        String[] componentsToTrack = {"x", "y", "z"};
    
        assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[0]).get());
        assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[1]).get());
        assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[2]).get());
    
        // cleanup and shutdown pool
        executor.shutdown();
        try {
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            // ignore this
        }
    }
    

    在执行此操作之前,应该删除try/catch方法中的run()

    您可能可以改进的另一件事是使executor成为测试类的一个字段,并使用@BeforeClass@Before、^{。。。要进行初始化,请在测试之间进行清理,并正常关闭池。请记住,从资源的角度来看,线程池并不便宜

    希望有帮助

    p.S.如果您的目标是并行处理ConcurrentComponentTracker,那么您可以将Future<?>存储在某些集合中,并在提交所有任务后运行断言

  2. # 2 楼答案

    无论是谁在评论中回答,然后将其删除,都为我解决了这个问题。我的主要JUnit线程没有等待其他线程完成。所以我把这些线钉到了最后,它果然起了作用:

    executor.shutdown();
    
    try {
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    }
    catch (InterruptedException e) {
        e.printStackTrace();
    }