这是我演员的样子

public final class DiskMonitorActor extends UntypedActor {

  private final File assetsDirectory;
  private final long thresholdPercentage;
  private final LoggingAdapter logging = Logging.getLogger(getContext().system(), this);

  public DiskMonitorActor(final File assetsDirectory, final long thresholdPercentage) {
    this.assetsDirectory = assetsDirectory;
    this.thresholdPercentage = thresholdPercentage;
    validateAssetsDirectory();
  }

  public static Props props(final File assetsDirectory, final long thresholdPercentage) {
    return Props.create(new Creator<DiskMonitorActor>() {
      private static final long serialVersionUID = 1L;

      public DiskMonitorActor create() throws Exception {
        return new DiskMonitorActor(assetsDirectory, thresholdPercentage);
      }
    });
  }

  private void validateAssetsDirectory() {
    if (!assetsDirectory.exists()) {
      throw new DiskException(assetsDirectory.getAbsolutePath() + " does not exists");
    }
    if (!assetsDirectory.isDirectory()) {
      throw new DiskException(assetsDirectory.getAbsolutePath() + " is not a directory");
    }
    if (!assetsDirectory.canRead()) {
      throw new DiskException(assetsDirectory.getAbsolutePath() + " does have read permission");
    }
  }

  @Override
  public void onReceive(final Object message) throws Exception {
    if (message instanceof DiskMonitorMessage) {
      logging.info("disk: {}, total space: {}, usable space: {}",
                   assetsDirectory.getAbsolutePath(),
                   assetsDirectory.getTotalSpace(),
                   assetsDirectory.getUsableSpace());
      if (isThresholdExceeded()) {
        logging.error("Disk full. Available Space {}", assetsDirectory.getFreeSpace());
        throw new DiskException("disk capacity reached threshold.");
      }

    } else {
      unhandled(message);
    }
  }

  private boolean isThresholdExceeded() {
    final long usedBytes = assetsDirectory.getTotalSpace() - assetsDirectory.getUsableSpace();
    final long thresholdBytes = assetsDirectory.getTotalSpace() * thresholdPercentage / 100;
    return usedBytes >= thresholdBytes;
  }
}

和测试
public class DiskMonitorActorTest {

  @Mock
  private File assetsDirectory;

  @Rule
  public TestName testName = new TestName();

  @Rule
  public ExpectedException expectedException = ExpectedException.none();

  @Before
  public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
  }

  @Test
  public void testDirectoryDoesNotExists() throws Exception {
    when(assetsDirectory.exists()).thenReturn(false);
    expectedException.expect(DiskException.class);
    expectedException.expectMessage("null does not exists");
    getDiskMonitorActor(assetsDirectory, 10L);
  }

  private DiskMonitorActor getDiskMonitorActor(final File assetsDirectory,
                                               final long threshold) {
    final Props props = DiskMonitorActor.props(assetsDirectory, threshold);
    final ActorSystem system = ActorSystem.create("system");

    final TestActorRef<DiskMonitorActor> actorRef =
        TestActorRef.create(system, props, testName.getMethodName());

    return actorRef.underlyingActor();
  }
}

当我运行它时,我看到
[ERROR] [04/26/2015 15:51:35.206] [system-akka.actor.default-dispatcher-2] [akka://system/user/testDirectoryDoesNotExists] null does not exists
akka.actor.ActorInitializationException: exception during creation
    at akka.actor.ActorInitializationException$.apply(Actor.scala:164)
    at akka.actor.ActorCell.create(ActorCell.scala:596)
    at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:456)
    at akka.actor.ActorCell.systemInvoke(ActorCell.scala:478)
    at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:279)
    at akka.testkit.CallingThreadDispatcher.process$1(CallingThreadDispatcher.scala:244)
    at akka.testkit.CallingThreadDispatcher.runQueue(CallingThreadDispatcher.scala:284)
    at akka.testkit.CallingThreadDispatcher.register(CallingThreadDispatcher.scala:153)
    at akka.dispatch.MessageDispatcher.attach(AbstractDispatcher.scala:132)
    at akka.actor.dungeon.Dispatch$class.start(Dispatch.scala:87)
    at akka.actor.ActorCell.start(ActorCell.scala:369)
    at akka.testkit.TestActorRef.<init>(TestActorRef.scala:50)
    at akka.testkit.TestActorRef$.apply(TestActorRef.scala:141)
    at akka.testkit.TestActorRef$.apply(TestActorRef.scala:137)
    at akka.testkit.TestActorRef$.create(TestActorRef.scala:160)
    at akka.testkit.TestActorRef.create(TestActorRef.scala)
    at com.self.monitoring.tenant.DiskMonitorActorTest.getDiskMonitorActor(DiskMonitorActorTest.java:69)
    at com.self.monitoring.tenant.DiskMonitorActorTest.testDirectoryDoesNotExists(DiskMonitorActorTest.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: com.self.monitoring.tenant.exception.DiskException: null does not exists
    at com.self.monitoring.tenant.DiskMonitorActor.validateAssetsDirectory(DiskMonitorActor.java:38)
    at com.self.monitoring.tenant.DiskMonitorActor.<init>(DiskMonitorActor.java:23)
    at com.self.monitoring.tenant.DiskMonitorActor$1.create(DiskMonitorActor.java:31)
    at com.self.monitoring.tenant.DiskMonitorActor$1.create(DiskMonitorActor.java:27)
    at akka.actor.CreatorConsumer.produce(Props.scala:335)
    at akka.actor.Props.newActor(Props.scala:252)
    at akka.actor.ActorCell.newActor(ActorCell.scala:552)
    at akka.actor.ActorCell.create(ActorCell.scala:578)
    ... 46 more

[INFO] [04/26/2015 15:51:35.211] [system-akka.actor.default-dispatcher-3] [akka://system/user/testDirectoryDoesNotExists] Message [akka.testkit.TestActorRef$InternalGetActor$] from Actor[akka://system/temp/$a] to TestActor[akka://system/user/testDirectoryDoesNotExists] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

java.lang.AssertionError:
Expected: (an instance of com.self.monitoring.tenant.exception.DiskException and exception with message a string containing "null does not exists")
     but: an instance of com.self.monitoring.tenant.exception.DiskException <java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]> is a java.util.concurrent.TimeoutException
Stacktrace was: java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]
    at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219)
    at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:223)
    at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:116)
    at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53)
    at scala.concurrent.Await$.result(package.scala:116)
    at akka.testkit.TestActorRef.underlyingActor(TestActorRef.scala:93)
    at com.self.monitoring.tenant.DiskMonitorActorTest.getDiskMonitorActor(DiskMonitorActorTest.java:71)
    at com.self.monitoring.tenant.DiskMonitorActorTest.testDirectoryDoesNotExists(DiskMonitorActorTest.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
java.lang.AssertionError:
Expected: (an instance of com.self.monitoring.tenant.exception.DiskException and exception with message a string containing "null does not exists")
     but: an instance of com.self.monitoring.tenant.exception.DiskException <java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]> is a java.util.concurrent.TimeoutException
Stacktrace was: java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]
    at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219)
    at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:223)
    at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:116)
    at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53)
    at scala.concurrent.Await$.result(package.scala:116)
    at akka.testkit.TestActorRef.underlyingActor(TestActorRef.scala:93)
    at com.self.monitoring.tenant.DiskMonitorActorTest.getDiskMonitorActor(DiskMonitorActorTest.java:71)
    at com.self.monitoring.tenant.DiskMonitorActorTest.testDirectoryDoesNotExists(DiskMonitorActorTest.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at org.junit.Assert.assertThat(Assert.java:956)
    at org.junit.Assert.assertThat(Assert.java:923)
    at org.junit.rules.ExpectedException.handleException(ExpectedException.java:252)
    at org.junit.rules.ExpectedException.access$000(ExpectedException.java:106)
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:241)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)


Process finished with exit code 255

我不明白我怎么看
Stacktrace was: java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]

什么是工作流程?我以为我的构造函数会抛出有效的异常,因此我应该能够轻松捕获ActorInitializationException
这里发生了什么?

最佳答案

超时是由underlyingActor方法引起的,该方法在对actor实例进行Await.result编码时在内部使用ask。而且由于您的演员永远不会被创建,因此这个ask将永远不会被满足。

要解决您的问题,您可以在其他actor内创建DiskMonitorActor actor,从而为DiskMonitorActor实例创建父对象,然后在创建时将Failure发送到它的context.parent(如here),或者您可以重构DiskMonitorActor逻辑,因此任何人在失败后向DiskMonitorActor发送消息的用户将收到Failure消息作为响应(在这种情况下,我建议使用become模式,例如针对失败和正常状态的不同接收方法)。第二种方法有点复杂,因为您需要确定何时在失败的actor中执行context.stop(self)

解决此问题的其他方法是通过消息传递目录,而不是通过构造函数传递目录,因此您可以先使用Failure然后使用context.stop对其进行响应。

简而言之,您所做的只是一点点的“akkish”。

关于java - Stacktrace是:java.util.concurrent.TimeoutException: future 在[5000毫秒]之后超时,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29884634/

10-11 04:50