为什么java ExecutorService newSingleThreadExecutor产生两个线程? [英] Why is java ExecutorService newSingleThreadExecutor spawning two threads?

查看:288
本文介绍了为什么java ExecutorService newSingleThreadExecutor产生两个线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个示例Java代码,在该代码下,如果作为控制台应用程序运行,其行为将达到我的预期(生成单个线程来执行可运行对象).

I have a sample java code below which if run as a console application behaves as I expected ( spawning a single thread to execute the runnable).

我看到的奇怪行为(产生两个线程-下面的示例)是当我使用Apache的prunsrv64.exe作为服务应用程序运行此示例时.

The strange behavior (spawning two threads - sample below) I see is when I run this sample as a service application using Apache's prunsrv64.exe.

我正在64位Windows 7计算机上对此进行测试.

I am testing this on a Windows 7 machine - 64bit.

样本输出:

   Thread -28 Current time: 09:50:11 AM
   Thread -52 Current time: 09:50:12 AM
   Thread -28 Current time: 09:50:21 AM
   Thread -52 Current time: 09:50:22 AM
   Thread -28 Current time: 09:50:31 AM
   Thread -52 Current time: 09:50:32 AM

示例代码:

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorTest{
    public void testIt(){
        ExecutorService ex = Executors.newSingleThreadExecutor();
        ex.execute(new Runnable(){
            public void run() {
                while(true){
                    System.out.printf("Thread -" + Thread.currentThread().getId() + " Current time: %tr%n", new Date());
                    try{
                        Thread.sleep(10000);    
                    }catch(InterruptedException ie){
                        ie.printStackTrace();
                    }                   
                }

            }
        });     
    }
}

谢谢.

更新: 为了澄清起见,我将这段代码称为:

Update: Just to clarify I am calling this code as follows:

    ExecutorTest tester = new ExecutorTest();
    tester.testIt();

相同的未经更改的代码在作为控制台应用程序和服务应用程序运行时表现出不同,如上所述.

The same code without changes is behaving differently when run as console application and a service application as I mentioned above.

更新2: 我添加了另一个使用ScheduledExecutorService的测试器.行为是相同的.

Update 2: I added a second tester which uses a ScheduledExecutorService. The behavior is the same.

Update2输出:

Update2 Output:

Using ScheduledExecutorService.
Thread Id outside Runnable -1
Thread -53 Current time: 10:58:15 AM
Thread -28 Current time: 10:58:24 AM
Thread -53 Current time: 10:58:25 AM
Thread -28 Current time: 10:58:34 AM
Thread -53 Current time: 10:58:35 AM
Thread -28 Current time: 10:58:44 AM
Thread -53 Current time: 10:58:45 AM
Thread -28 Current time: 10:58:54 AM
Thread -53 Current time: 10:58:55 AM
Thread -28 Current time: 10:59:04 AM
Thread -53 Current time: 10:59:05 AM

更新2个代码:

public void testItWithScheduled(){
    System.out.println("Using ScheduledExecutorService.");
    ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
    System.out.println("Thread Id outside Runnable -" + Thread.currentThread().getId());
    ex.scheduleWithFixedDelay(new Runnable(){
        public void run() {
            System.out.printf("Thread -" + Thread.currentThread().getId() + " Current time: %tr%n", new Date());
        }
    },0L, 10, TimeUnit.SECONDS);        
}


called through:

    ExecutorTest tester = new ExecutorTest();
    tester.testItWithScheduled();


更新3: 修改日志记录以添加身份哈希


Update 3: Modified logging to add identity hash

Using ScheduledExecutorService.
Thread Id outside Runnable 1 with reference: 1370756928
Thread -53 Current time: 11:10:38 AM with reference: 1370756928
Thread -28 Current time: 11:10:47 AM with reference: 1939972532
Thread -53 Current time: 11:10:48 AM with reference: 1370756928
Thread -28 Current time: 11:10:57 AM with reference: 1939972532
Thread -53 Current time: 11:10:58 AM with reference: 1370756928
Thread -28 Current time: 11:11:07 AM with reference: 1939972532
Thread -53 Current time: 11:11:08 AM with reference: 1370756928

推荐答案

唯一合理的结论是您(或框架)正在创建ExecutorTest的两个引用并执行两次.

The only reasonable conclusion is that you (or the framework) are creating two references of ExecutorTest and executing it twice.

将对象的identityHashCode添加到您的日志记录中.

Add the identityHashCode of the object to your logging.

System.out.printf("Thread -" + Thread.currentThread().getId() + " Current time: %tr with reference: %s%n ", new Date(), System.identityHashCode(ExecutorTest.this));


相同的没有更改的代码在作为控制台应用程序和服务应用程序运行时表现出不同,如上所述.

The same code without changes is behaving differently when run as console application and a service application as I mentioned above.

您可以完全控制在这里创建的数量.

You control exactly how many are being created here.

修改.基于您的第三次更新.

Edit Based on your third update.

我的假设是正确的,对象的System.identityHashCode类似于其内存位置.如您所见,这两个值是不同的,但是如果ExecutorService正在创建两个线程,则这些值将是相同的.

My assumption is correct, the System.identityHashCode of an object is analogous to its memory location. As you can see the two values are different but if the ExecutorService was creating two threads, those values would be the same.

这意味着您正在创建多个实例.也许不是您直接,而是该框架正在创建多个相同的服务并运行它们.

That means you are creating multiple instances. Maybe not you directly, but the framework is creating multiple of the same service and running them.

因此,这从为什么执行程序服务会创建两个线程"这一问题过渡到为什么我的框架会创建两个服务实例".这个问题我无法回答.

So this moves from a question of 'why is the executor service creating 2 threads' to 'why is my framework creating two service instances'. That question I cannot answer.

为清楚起见,请想象像这样执行测试

To clarify more clearly, imagine executing your test like this

ExecutorTest tester1 = new ExecutorTest();
tester1.testIt();
ExecutorTest tester2 = new ExecutorTest();
tester2.testIt();

这与您的应用程序中发生的事情类似.

That is similar to what is occurring in your application.

这篇关于为什么java ExecutorService newSingleThreadExecutor产生两个线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆