英文:
Java newSingleThreadExecutor seems to create many threads
问题
我有一个任务,由于它需要大量资源,我想以异步方式执行它,因此我想要一个单线程执行器池,在第一个任务完成后将启动下一个任务。
通过我的主应用程序线程,我可能会多次调用此任务。
我编写了一个简单的测试,我发现不是每隔5秒钟(我设置的人为延迟)调用一次单个线程,而是被多次调用。
这是我的类:
public class NoTypeHandlerService {
private Executor pool;
private static NoTypeHandlerService instance = null;
@Getter
private int SECONDS_TO_WAIT_BETWEEN_JOBS = 5;
private NoTypeHandlerService() {
pool = Executors.newSingleThreadExecutor();
}
public static NoTypeHandlerService getInstance() {
if (instance == null) {
instance = new NoTypeHandlerService();
}
return instance;
}
public void assignType(ComplianceCandidate candidate) {
CompletableFuture.supplyAsync(() -> candidate, pool).thenApplyAsync(AssignType::doWork);
}
}
AssignType
类是任务:
public class AssignType {
public static ComplianceCandidate doWork(ComplianceCandidate candidate) {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
log.error("Could not execute type assignation job for: {}", candidate);
}
log.debug("Proceeding to assign type for: {}", candidate);
return candidate;
}
}
这是我的简单测试类:
@Test
@DisplayName("Creates fake candidates and make type service")
public void testTypeAssignationTest() throws InterruptedException {
ComplianceDevice device = new ComplianceDevice("0X123456", "99.6.6.1", 1, 1);
ComplianceDevice device1 = new ComplianceDevice("0X1234567", "99.6.6.1", 1, 1);
ComplianceDevice device2 = new ComplianceDevice("0X12345678", "99.6.6.1", 1, 1);
ComplianceCandidate candidate = new ComplianceCandidate(device);
ComplianceCandidate candidate1 = new ComplianceCandidate(device1);
ComplianceCandidate candidate2 = new ComplianceCandidate(device2);
NoTypeHandlerService.getInstance().assignType(candidate);
NoTypeHandlerService.getInstance().assignType(candidate1);
NoTypeHandlerService.getInstance().assignType(candidate2);
log.debug("Successfully entered all jobs to execution");
TimeUnit.SECONDS.sleep(15);
}
当我运行这个测试时,我看到以下日志:
2020-07-26 21:36:50 [main] - Successfully entered all jobs to execution
2020-07-26 21:36:55 [ForkJoinPool.commonPool-worker-7] - Proceeding to assign type for: ComplianceCandidate [device=[ipAddress=99.6.6.1, macAddress=0X12345678, type=null]]
2020-07-26 21:36:55 [ForkJoinPool.commonPool-worker-5] - Proceeding to assign type for: ComplianceCandidate [device=[ipAddress=99.6.6.1, macAddress=0X1234567, type=null]]
2020-07-26 21:36:55 [ForkJoinPool.commonPool-worker-3] - Proceeding to assign type for: ComplianceCandidate [device=[ipAddress=99.6.6.1, macAddress=0X123456, type=null]]
这不是我期望的行为,虽然主线程确实没有被阻塞,但是我并没有看到只有一个 ForkJoinPool.commonPool-worker-7 每隔5秒打印一次,我看到3个都在同一时间打印。
英文:
I have a task that i want to do in an async manner since its resource intensive, therefore i want a single thread executor pool that will start the next task once the first one is completed
through my main application thread i might call this task numerous times
i wrote a simple test and I'm seeing that instead of a single thread being called every 5 seconds (the artificial delay i placed to simulate), its being called many times
here is my class
public class NoTypeHandlerService {
private Executor pool;
private static NoTypeHandlerService instance = null;
@Getter
private int SECONDS_TO_WAIT_BETWEEN_JOBS = 5;
private NoTypeHandlerService() {
pool = Executors.newSingleThreadExecutor();
}
public static NoTypeHandlerService getInstance() {
if (instance == null) {
instance = new NoTypeHandlerService();
}
return instance;
}
public void assignType(ComplianceCandidate candidate) {
CompletableFuture.supplyAsync(()-> candidate, pool).thenApplyAsync(AssignType::doWork);
}
}
AssignType class is the task
public class AssignType {
public static ComplianceCandidate doWork(ComplianceCandidate candidate) {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
log.error("Could not execute type assignation job for: {}", candidate);
}
log.debug("Proceeding to assign type for: {}", candidate);
return candidate;
}
}
here is my simple test class
@Test
@DisplayName("Creates fake candidates and make type service")
public void testTypeAssignationTest() throws InterruptedException {
ComplianceDevice device = new ComplianceDevice("0X123456", "99.6.6.1", 1, 1);
ComplianceDevice device1 = new ComplianceDevice("0X1234567", "99.6.6.1", 1, 1);
ComplianceDevice device2 = new ComplianceDevice("0X12345678", "99.6.6.1", 1, 1);
ComplianceCandidate candidate = new ComplianceCandidate(device);
ComplianceCandidate candidate1 = new ComplianceCandidate(device1);
ComplianceCandidate candidate2 = new ComplianceCandidate(device2);
NoTypeHandlerService.getInstance().assignType(candidate);
NoTypeHandlerService.getInstance().assignType(candidate1);
NoTypeHandlerService.getInstance().assignType(candidate2);
log.debug("Successfully entered all jobs to execution");
TimeUnit.SECONDS.sleep(15);
}
when i run this i see the following logs
2020-07-26 21:36:50 [main] - Successfully entered all jobs to execution
2020-07-26 21:36:55 [ForkJoinPool.commonPool-worker-7] - Proceeding to assign type for: ComplianceCandidate [device=[ipAddress=99.6.6.1, macAddress=0X12345678, type=null]]
2020-07-26 21:36:55 [ForkJoinPool.commonPool-worker-5] - Proceeding to assign type for: ComplianceCandidate [device=[ipAddress=99.6.6.1, macAddress=0X1234567, type=null]]
2020-07-26 21:36:55 [ForkJoinPool.commonPool-worker-3] - Proceeding to assign type for: ComplianceCandidate [device=[ipAddress=99.6.6.1, macAddress=0X123456, type=null]]
this is not the behavior i was hoping for, while the main thread is indeed not blocked, instead of seeing only one of these guys ForkJoinPool.commonPool-worker-7 printing every 5 seconds, I'm seeing 3 of them all printing at the same time
专注分享java语言的经验与见解,让所有开发者获益!
评论