gpt4 book ai didi

java - 为什么java并发测试失败?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:17:33 24 4
gpt4 key购买 nike

我有一个简单的类:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DummyService {
private final Logger logger = LoggerFactory.getLogger(getClass());
private boolean dataIndexing = false;

public boolean isDataIndexing() {
logger.info("isDataIndexing: {}", dataIndexing);
return dataIndexing;
}

public void cancelIndexing() {
logger.info("cancelIndexing: {}", dataIndexing);
dataIndexing = false;
}

public void createIndexCorp() {
logger.info("createIndexCorp: {}", dataIndexing);
createIndex();
}

public void createIndexEntr() {
logger.info("createIndexEntr: {}", dataIndexing);
createIndex();
}

private void createIndex() {
logger.info("createIndex: {}", dataIndexing);
if(dataIndexing)
throw new IllegalStateException("Service is busy!");
dataIndexing = true;
try {
while(dataIndexing) {
Thread.sleep(100);
logger.debug("I am busy...");
}
logger.info("Indexing canceled");
} catch (InterruptedException e) {
logger.error("Error during sleeping", e);
} finally {
dataIndexing = false;
}
}
}

和一个单元测试,我想用它来测试对象的行为:

public class CommonUnitTest
{
@Test
public void testCreateIndexWithoutAsync() throws InterruptedException {
final long sleepMillis = 500;
final DummyService indexService = new DummyService();
assertFalse(indexService.isDataIndexing());
new Thread(() -> {
indexService.createIndexCorp();
}
).start();
Thread.sleep(sleepMillis);
assertTrue(indexService.isDataIndexing());
// TaskExecutor should fails here
new Thread(() -> {
indexService.createIndexEntr();
logger.error("Exception expected but not occurred");
}
).start();
assertTrue(indexService.isDataIndexing());
indexService.cancelIndexing();
Thread.sleep(sleepMillis);
assertFalse(indexService.isDataIndexing());
}
}

对象的行为必须是:如果方法 createIndexCorp 或 createIndexEntr 被一个线程调用,则另一个线程必须通过尝试调用此方法之一来获得异常。但这不会发生!这是日志:

2015-10-15 17:15:06.277  INFO   --- [           main] c.c.o.test.DummyService                  : isDataIndexing: false
2015-10-15 17:15:06.318 INFO --- [ Thread-0] c.c.o.test.DummyService : createIndexCorp: false
2015-10-15 17:15:06.319 INFO --- [ Thread-0] c.c.o.test.DummyService : createIndex: false
2015-10-15 17:15:06.419 DEBUG --- [ Thread-0] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:06.524 DEBUG --- [ Thread-0] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:06.624 DEBUG --- [ Thread-0] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:06.724 DEBUG --- [ Thread-0] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:06.818 INFO --- [ main] c.c.o.test.DummyService : isDataIndexing: true
2015-10-15 17:15:06.820 INFO --- [ main] c.c.o.test.DummyService : isDataIndexing: true
2015-10-15 17:15:06.820 INFO --- [ Thread-1] c.c.o.test.DummyService : createIndexEntr: true
2015-10-15 17:15:06.820 INFO --- [ main] c.c.o.test.DummyService : cancelIndexing: true
2015-10-15 17:15:06.820 INFO --- [ Thread-1] c.c.o.test.DummyService : createIndex: true
2015-10-15 17:15:06.824 DEBUG --- [ Thread-0] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:06.921 DEBUG --- [ Thread-1] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:06.924 DEBUG --- [ Thread-0] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:07.021 DEBUG --- [ Thread-1] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:07.024 DEBUG --- [ Thread-0] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:07.121 DEBUG --- [ Thread-1] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:07.124 DEBUG --- [ Thread-0] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:07.221 DEBUG --- [ Thread-1] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:07.224 DEBUG --- [ Thread-0] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:07.321 DEBUG --- [ Thread-1] c.c.o.test.DummyService : I am busy...
2015-10-15 17:15:07.321 INFO --- [ main] c.c.o.test.DummyService : isDataIndexing: true

您可以看到第二个线程可以启动进程,但它应该得到异常。测试代码中的最后一个断言也失败了。怎么会这样?我不明白这种行为。我尝试使用 volatile 和 synchronized 关键字,但没有任何帮助。 DummyService 有什么问题?

最佳答案

您有 3 个线程,t0、t1 和 tm(主线程)。操作顺序是这样的:

tm starts t0
t0 checks dataIndexing flag - false, goes into the loop, sets flag to true
tm sleeps
tm starts t1
tm sets indexing flag to false
t1 checks dataIndexing flag - false, goes into the loop, sets flag to true
t0 continues the loop because it missed that brief period when indexing was cancelled

如果在将索引标志设置为 false 之前在主 tm 中 hibernate ,则 t1 将得到异常。您需要同步访问多个线程之间共享的变量。 IE。检查标志的状态并更改它需要在持有互斥锁的同时完成。

关于java - 为什么java并发测试失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33151051/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com