在下面的代码中,javascript运行在与主线程不同的单独线程中。该脚本是一个无限循环,因此需要以某种方式终止。怎样
使命感脚本开始运行后,cancel()不起作用。但如果我打电话。cancel()在线程初始化之后,它将终止它(注释掉的行)。
package testscriptterminate;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.Timer;
import java.util.TimerTask;
public class TestScriptTerminate extends TimerTask{
private ExecutorService threads;
private Future runScript;
private Timer t;
public TestScriptTerminate(){
t = new Timer();
t.schedule(this, 6000); //let the script run for a while before attempt to cancel
threads = Executors.newFixedThreadPool(1);
runScript = threads.submit(new ScriptExec());
//runScript.cancel(true); //will cancel here, before the script had a change to run, but useless, i want to cancel at any time on demand
}
@Override
public void run(){
//after script has fully initialized and ran for a while - attempt to cancel.
//DOESN'T WORK, thread still active
System.out.println("Canceling now...");
runScript.cancel(true);
}
public static void main(String[] args) {
new TestScriptTerminate();
}
}
class ScriptExec implements Runnable{
private ScriptEngine js;
private ScriptEngineManager scriptManager;
public ScriptExec(){
init();
}
@Override
public void run() {
try {
js.eval("while(true){}");
} catch (ScriptException ex) {
System.out.println(ex.toString());
}
}
private void init(){
scriptManager = new ScriptEngineManager();
js = scriptManager.getEngineByName("nashorn");
}
}
不幸的是,它不适用于简单的无限循环:while(true){}
。我尝试了线程。取消()
不会导致线程退出。我希望在IntelliJ插件中运行脚本时能够做到万无一失,因为用户可能会犯错误,导致无限循环,从而挂起插件。
我发现在大多数情况下唯一有效的是线程。停止()。即使这样,对于这样的脚本也不起作用:
while(true) {
try {
java.lang.Thread.sleep(100);
} catch (e) {
}
}
javascript捕获java。lang.ThreadDeath异常并继续。我发现,即使有几个线程,上面的示例也不可能中断。stop()
一个接一个地发出。为什么要使用多个?希望其中一个能在异常处理代码中捕获线程并中止它。如果catch块中有像var i=“e”这样简单的东西需要处理,那么它就可以工作
这足以导致第二个线程。stop()结束它。
因此,这个故事的寓意是,在纳肖恩,没有一种html" target="_blank">安全可靠的方式来结束失控的剧本,但在大多数情况下,有一种方法是可行的。
我的实现发出一个Thread.interrupt()
,然后礼貌地等待2秒钟线程终止,如果失败,则发出Thread.stop()
两次。如果这不起作用,那么其他任何东西也不会起作用。
希望它能帮助人们省去数小时的实验,找到一种更可靠的方法来阻止nashorn失控的脚本,而不是希望正在运行的脚本能够配合线程。取消()。
JavaScript(在Nashorn下)与Java一样,不会在紧密循环的中间响应中断。脚本需要轮询中断并自动终止循环,或者它可以调用一些检查中断的东西,并让中断异常传播。
你可能会认为Nashorn“只是在运行一个脚本”,应该立即中断它。这不适用,原因与Java中不适用的原因相同:异步中断有损坏应用程序数据结构的风险,基本上无法避免或从中恢复。
异步中断带来的问题与长期被弃用的线程相同。停止方法。本文件对此进行了解释,它是注释中链接的文件的更新版本。
Java线程原语弃用
另请参阅Goetz,Java实践中的并发,第7章,取消和关闭。
检查中断的最简单方法是调用线程。中断()。您可以很容易地从JavaScript调用它。下面是对示例程序的重写,该程序会在五秒钟后取消正在运行的脚本:
public class TestScriptTerminate {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
void script() {
ScriptEngineManager scriptManager = new ScriptEngineManager();
ScriptEngine js = scriptManager.getEngineByName("nashorn");
try {
System.out.println("Script starting.");
js.eval("while (true) { if (java.lang.Thread.interrupted()) break; }");
System.out.println("Script finished.");
} catch (ScriptException ex) {
ex.printStackTrace();
}
}
void init() throws Exception {
Future<?> scriptTask = pool.submit(this::script);
pool.schedule(() -> {
System.out.println("Canceling now...");
scriptTask.cancel(true);
}, 5, TimeUnit.SECONDS);
pool.shutdown();
}
public static void main(String[] args) throws Exception {
new TestScriptTerminate().init();
}
}
由于我们正在启动一个线程池,不妨将其设为一个计划线程池,以便我们可以将其用于脚本任务和超时。这样我们就可以避免Timer
和TimerTask
,无论如何,它们大多被SchduledExecutorService
替换。
处理和中断时通常的惯例是恢复中断位或让中断异常传播。(永远不要忽视中断。)由于中断循环可以被视为已经完成了中断的处理,因此这两种情况都不是必需的,只需让脚本正常退出就足够了。
这种重写还将大量工作从构造函数转移到了一个init()方法中。这可以防止实例从构造函数中泄漏到其他线程。在原始示例代码中没有明显的危险——事实上,几乎从来没有危险——但避免从构造函数中泄漏实例始终是一种很好的做法。
所以这是旧的,但我只是写了这篇文章,并认为这可能是有价值的分享。默认情况下,您无法停止Nashorn脚本的执行,。取消()
线程。stop()
线程。interrupt()
什么都不做,但是如果您愿意付出一些努力,并且可以重写一些字节码,那么这是可以实现的。细节:
http://blog.getsandbox.com/2018/01/15/nashorn-interupt/
问题内容: 在下面的代码中,我使javascript在与主要线程不同的线程中运行。该脚本是一个无限循环,因此需要以某种方式终止。怎么样? 脚本开始运行后,调用.cancel()无效。但是,如果我在线程初始化之后立即调用.cancel(),它将终止它(注释行)。 问题答案: 与Java一样,JavaScript(在Nashorn下)也不会像Java那样在紧密循环中响应中断。该脚本需要轮询中断并自动终
如果以下代码在多线程应用程序中可以工作,您可以帮助我吗。 这是我的Java脚本,将由Nashorn评估 这就是我创建脚本引擎的方式 在使用Testng进行测试时,此操作不会出现任何错误 测试结果1-请注意,有些数据是重复的 但是,如果我添加"并行=true"到@DataProvider我的脚本开始失败 测试结果2-请注意,重复一些数据,以表明相同的参考编号可能在测试过程中随机失败 有人可以确认我是
我想在服务器上呈现d3图表。我有三个选择:节点、幻影和纳肖恩。 我更喜欢Nashorn,因为我的API是Scala Play,我不想管理另一个进程。(部署、加载、排队等) 所以现在我需要让JSDom在Nashorn中工作,这样D3将有一些东西可以渲染。 到目前为止,这是可行的,但我不知道如何添加jsdom
问题内容: 您将如何依次执行三个线程?例如。线程1,线程2,线程3。不可能将一个线程的引用传递给另一个线程并从run()方法调用。 因此代码应如下所示: 并应该把 这可以通过使用ThreadPoolExecutor并使用阻塞队列来实现,但即使那样也不是可以接受的答案。 问题答案: 在java.util.concurrent包中使用ExecutorService。更精确地使用
问题内容: 我有一个线程,需要每10秒执行一次。该线程包含对另一台服务器上的数据库的多次调用(12-15)。此外,它还可以访问大约3个文件。因此,将有大量的IO和网络开销。 执行上述操作的最佳策略是什么? 一种方法是将sleep方法与while循环一起使用,但这将是一个糟糕的设计。 在这种情况下,类似于Timer的类会有所帮助吗?另外,最好创建几个更多的线程(一个用于IO,一个用于JDBC),而不
这个教程中,你会通过简单易懂的代码示例,来了解Nashorn JavaScript引擎。Nashorn JavaScript引擎是Java SE 8 的一部分,并且和其它独立的引擎例如Google V8(用于Google Chrome和Node.js的引擎)互相竞争。Nashorn通过在JVM上,以原生方式运行动态的JavaScript代码来扩展Java的功能。 在接下来的15分钟内,你会学到如何