Ecco po 'di codice che mostra l'attuazione Futuro e il filo .stop() uno. Questo è un problema interessante e sottolinea la necessità di un hook in uno ScriptEngine per poter interrompere qualunque script sia in esecuzione per qualsiasi motivo. Mi chiedo se questo potrebbe infrangere le ipotesi nella maggior parte delle implementazioni dal momento che assumono che eval()
verrà eseguito in un ambiente a thread singolo (bloccante)?
In ogni caso, i risultati dell'esecuzione del codice qui sotto:
// exec with Thread.stop()
$ java ExecJavascript
Java: Starting thread...
JS: Before infinite loop...
Java: ...thread started
Java: Thread alive after timeout, stopping...
Java: ...thread stopped
(program exits)
// exec with Future.cancel()
$ java ExecJavascript 1
Java: Submitting script eval to thread pool...
Java: ...submitted.
JS: Before infinite loop...
Java: Timeout! trying to future.cancel()...
Java: ...future.cancel() executed
(program hangs)
Ecco il programma completo:
import java.util.concurrent.*;
import javax.script.*;
public class ExecJavascript
{
private static final int TIMEOUT_SEC = 5;
public static void main(final String ... args) throws Exception
{
final ScriptEngine engine = new ScriptEngineManager()
.getEngineByName("JavaScript");
final String script =
"var out = java.lang.System.out;\n" +
"out.println('JS: Before infinite loop...');\n" +
"while(true) {}\n" +
"out.println('JS: After infinite loop...');\n";
if (args.length == 0) {
execWithThread(engine, script);
}
else {
execWithFuture(engine, script);
}
}
private static void execWithThread(
final ScriptEngine engine, final String script)
{
final Runnable r = new Runnable() {
public void run() {
try {
engine.eval(script);
}
catch (ScriptException e) {
System.out.println(
"Java: Caught exception from eval(): " + e.getMessage());
}
}
};
System.out.println("Java: Starting thread...");
final Thread t = new Thread(r);
t.start();
System.out.println("Java: ...thread started");
try {
Thread.currentThread().sleep(TIMEOUT_SEC * 1000);
if (t.isAlive()) {
System.out.println("Java: Thread alive after timeout, stopping...");
t.stop();
System.out.println("Java: ...thread stopped");
}
else {
System.out.println("Java: Thread not alive after timeout.");
}
}
catch (InterruptedException e) {
System.out.println("Interrupted while waiting for timeout to elapse.");
}
}
private static void execWithFuture(final ScriptEngine engine, final String script)
throws Exception
{
final Callable<Object> c = new Callable<Object>() {
public Object call() throws Exception {
return engine.eval(script);
}
};
System.out.println("Java: Submitting script eval to thread pool...");
final Future<Object> f = Executors.newCachedThreadPool().submit(c);
System.out.println("Java: ...submitted.");
try {
final Object result = f.get(TIMEOUT_SEC, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
System.out.println("Java: Interrupted while waiting for script...");
}
catch (ExecutionException e) {
System.out.println("Java: Script threw exception: " + e.getMessage());
}
catch (TimeoutException e) {
System.out.println("Java: Timeout! trying to future.cancel()...");
f.cancel(true);
System.out.println("Java: ...future.cancel() executed");
}
}
}
fonte
2009-10-21 15:06:29
-1 Se il battistrada non è in attesa, non ci sarà un'eccezione. Quindi, non funzionerà con un ciclo infinito. Il codice dovrebbe controllare 'Thread.currentThread(). Interrupted()' perché i tuoi suggerimenti funzionino. – sfussenegger
Argh, mancava quello. Ciò lascia solo la fermata deprecata() credo? –
ha cambiato il mio voto – sfussenegger