Здорово, вы помните про новые классы и их методы ;-/
На самом деле решение зависит от общей задачи, в самом простом случае я бы сделал "классически":
public static class OriginalTimeLimiter implements Runnable { private final Original o; private final Object in; private Object result; private Exception exception; private boolean done;
private OriginalTimeLimiter (final Original o, final Object in) { this.o = o; this.in = in; }//new
@Override public void run () { Object r; Exception ex; boolean dn = false;
private synchronized Object get () throws MyException, InterruptedException { if (exception instanceof MyException) { throw (MyException) exception; }
if (exception instanceof RuntimeException) { throw (RuntimeException) exception; }
if (!done) { throw new InterruptedException("timeout"); }
return result;//can be null, if invoke result can be null }//get
public static Object invoke (Original o, Object in, int timeSeconds) throws MyException, InterruptedException { final OriginalTimeLimiter r = new OriginalTimeLimiter(o, in); final Thread t = new Thread(r); t.start();
На самом деле решение зависит от общей задачи, в самом простом случае я бы сделал "классически":
public static class OriginalTimeLimiter implements Runnable {
private final Original o;
private final Object in;
private Object result;
private Exception exception;
private boolean done;
private OriginalTimeLimiter (final Original o, final Object in) {
this.o = o; this.in = in;
}//new
@Override public void run () {
Object r; Exception ex; boolean dn = false;
try {
r = o.invoke(in);
ex = null; dn = true;
} catch (Exception e) {
r = null; ex = e;
}
synchronized (this) {
result = r; exception = ex; done = dn;
}
}//run
private synchronized Object get () throws MyException, InterruptedException {
if (exception instanceof MyException) {
throw (MyException) exception;
}
if (exception instanceof RuntimeException) {
throw (RuntimeException) exception;
}
if (!done) {
throw new InterruptedException("timeout");
}
return result;//can be null, if invoke result can be null
}//get
public static Object invoke (Original o, Object in, int timeSeconds) throws MyException, InterruptedException {
final OriginalTimeLimiter r = new OriginalTimeLimiter(o, in);
final Thread t = new Thread(r);
t.start();
try {
t.join(timeSeconds*1000L);
} catch (InterruptedException e) {
t.interrupt();
Thread.currentThread().interrupt();
throw e;
}
final Object tmp = r.get();
t.interrupt();
return tmp;
}//invoke
}//OriginalTimeLimiter
@Test public void testTimeout () throws MyException, InterruptedException {
final Original o = new Original();
try {
OriginalTimeLimiter.invoke(o, null, 1);
fail("Null должен генерировать MyException");
} catch (InterruptedException e) {
fail("Null должен генерировать MyException");
} catch (MyException e) {}
assertEquals("", OriginalTimeLimiter.invoke(o, "", 1));
assertEquals("[test]", OriginalTimeLimiter.invoke(o, "test", 3));
assertEquals("{1}", OriginalTimeLimiter.invoke(o, 1, 3));
try {
OriginalTimeLimiter.invoke(o, "ops", 1);
fail("Null должен генерировать InterruptedException");
} catch (InterruptedException e) {
assertEquals("timeout", e.getMessage());
} catch (MyException e) {
fail("Null должен генерировать InterruptedException");
}
try {
assertEquals(20000000L, OriginalTimeLimiter.invoke(o, 1, 1));
fail("Null должен генерировать InterruptedException");
} catch (InterruptedException e) {
assertEquals("timeout", e.getMessage());
} catch (MyException e) {
fail("Null должен генерировать InterruptedException");
}
}//testTimeout
Reply
Leave a comment