Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ExecutorService.execute()以静默方式退出run()方法_Java_Multithreading_Junit_Executorservice - Fatal编程技术网

Java ExecutorService.execute()以静默方式退出run()方法

Java ExecutorService.execute()以静默方式退出run()方法,java,multithreading,junit,executorservice,Java,Multithreading,Junit,Executorservice,尝试测试我的一个类是否可以处理在多个线程上被访问的问题。我有一个JUnit测试,其中我创建了一个类来实现Runnable并运行我的类 当我运行execute时,它到达run()方法中的一行,并在该线程上退出,而不报告任何问题,我用Try-Catch(Throwable)将其包装起来,但仍然没有出现问题的迹象 这是我的密码: class ConcurrencyTests { class ConcurrentComponentTracker implements Runnable {

尝试测试我的一个类是否可以处理在多个线程上被访问的问题。我有一个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]));
    }
}
以及输出:

要跟踪的组件:[x]

要跟踪的组件:[y]

要跟踪的组件:[z]


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

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

executor.shutdown();

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

JUnit测试实际上应该测试和验证结果。在这种特殊情况下,测试产生的输出应该由开发人员/测试人员验证,因此这不是自动化。 我建议您使用
Future
来跟踪任务执行的状态。对于
Runnable
任务
get()
Future的方法
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
    }
}
在执行此操作之前,应删除
run()
方法中的
try/catch

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

希望有帮助


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

当我无法使用
main
方法复制注释时,我删除了注释。这实际上是一个有趣的案例:只有当我用JUnit测试主线程时,它才会终止。将其作为普通java应用程序运行效果很好(我不知道junit会做这样的事情)