假设我有一个在提交给ExecutorService的任务中调用的第三方Java库。
我相信第三方库不是恶意的,但极有可能出现编程错误,导致它陷入无限循环,如果是这种情况,我无法修复它以解决这些罕见的情况。
处理这个问题的最佳方法是什么,这样应用程序就不会陷入困境?是否足够好来处理这种情况?
有一个相关的问题在ExecutorService任务中停止无限循环,但这依赖于程序员的合作能力和检测Thread.currentThread(). is中断()
以停止处理,我不能依赖。
(在我的例子中,它是Jython代码;在Jython的早期版本中,解释器显然没有检查Thread.currentThread(). isInterunc()
,不确定它现在做什么...但是我的问题对于任何第三方Java代码都是通用的。)
在正确阅读了问题之后,我整理了这组课程。相对简单:一个Runnable连接到套接字,从调用不稳定库的辅助jvm发送输入并检索输出。
如果在3次尝试后未收到响应,则会终止辅助jvm。但它可以重新启动。辅助jvm有一个退出挂钩来关闭套接字。
class SafetyValve implements Runnable{
PrintWriter out;
BufferedReader in;
Socket s = null;
AtomicBoolean flag;
SafetyValve(AtomicBoolean b){
flag = b;
}
@Override
public void run() {
try {
s = new Socket("localhost", 9000);
out = new PrintWriter(s.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
while (!Thread.currentThread().isInterrupted()){
flag.set(false);
out.print(0);
out.flush();
System.out.print(in.read());
flag.set(true);
}
} catch (Exception e) {
e.printStackTrace();
}
finally{
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Main/Controller类。它使用Thread类进行控制
public class Switch {
public static void main(String[] args) {
try {
AtomicBoolean flag = new AtomicBoolean(false);
int counter = 0;
ProcessBuilder pb = ...
pb.directory(,,,);
Process p = pb.start();
SafetyValve sv = new SafetyValve(flag);
Thread t = new Thread(sv);
t.start();
while(t.getState() != Thread.State.RUNNABLE){
Thread.sleep(10);
}
while(true){
if (flag.get() == false){
if (++counter == 3){
while(t.getState() != Thread.State.TERMINATED){
p.destroyForcibly();
t.interrupt();
Thread.sleep(10);
}
break;
}
}
else
counter = 0;
Thread.sleep(100);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
辅助jvm有一个标准的服务器套接字实现:
class UnYielding{
int i = 0;
int returnInt(){
i++;
if (i > 2)
while(true);
return i;
}
}
class Hook extends Thread{
RunWild rw;
Hook(RunWild wr){
rw = wr;
}
public void run() {
try {
System.out.println("exit...");
System.out.flush();
rw.socket.close();
rw.server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class RunWild {
ServerSocket server;
Socket socket;
RunWild(){
Runtime.getRuntime().addShutdownHook(new Hook(this));
}
public static void main(String[] args){
UnYielding u;
int i;
PrintWriter out;
BufferedReader in;
RunWild rw = new RunWild();
try {
rw.server = new ServerSocket(9000);
rw.socket = rw.server.accept();
out = new PrintWriter(rw.socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(rw.socket.getInputStream()));
u = new UnYielding();
while ((i = in.read()) != -1){
out.print(u.returnInt());
out.flush();
Thread.sleep(10);
System.out.print("waiting...");
System.out.flush();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
我已经在OS X上对1.8进行了测试,它按预期工作。如果需要这种不稳定的类,这是一种方法
如果任务有一个无限循环,该循环不检查线程中断状态,也不使用引发中断异常的方法,那么它不会被关闭。
无法完成程序的简单示例:
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(1);
e.submit(() -> { while (true); });
e.shutdownNow();
System.out.println("Main is finished but the app keeps running");
}
一种方法是将线程作为守护程序运行:
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(1, r -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
});
e.submit(() -> { while (true); });
e.shutdownNow();
System.out.println("Main is finished and the app can exit");
}
问题内容: 有没有一种方法可以停止执行无限循环的线程? 问题答案: 是的,您可以将替换(或在逻辑上)。 这样,当任务取消时,循环将终止。 循环看起来像这样: 使用应该是这样的:
我将可调用任务(使用submit())提交给ExecutionService的实现。有时我似乎遇到了死锁,但无法工作在哪里或为什么会发生,所以我想为任务设置一个超时,我不清楚是如何做到的? 我应该吗 在提交任务时,在ExecutionService上使用invokeAny()而不是submit()并设置超时。我使用submit()一次提交许多任务,我是否也可以这样使用invokeAny(),我很谨
> 在将所有内容提交给后, 在上调用 则在shutdown()之前提交的所有任务都实际完成运行之前,awaitTermination()才返回。--然后在上调用,但是由于提交给的所有任务都已完成,并且从上的任务中提交给的所有任务都已提交给,所以在上调用之前,所有任务都已提交给。--对于以此类推 但是,我现在添加了这样一种情况,即可以将datapacket分解成一个较小的包,并在上提交额外的任务,而
我正在尝试将一个任务提交给Java的ExecutorService。它要么需要一个Callable,它允许抛出异常,要么需要一个Runnable。我的用例是愚蠢的:我想安排一个抛出异常的任务,但它是一个无效的方法。因此,我不能使用Callable或Runnable,因为方法定义与我的用例不匹配。我还想让我的异常从提交后收到的Future传播。有什么想法吗?
问题内容: 我正在尝试使用Java的类来运行大量具有固定数量线程的重量级任务。每个任务都有很多地方,在这些地方可能会由于异常而失败。 我已经继承了子类,并且重写了应该提供运行任务时遇到的任何未捕获异常的方法。但是,我似乎无法使其工作。 例如: 该程序的输出是“一切都很好-情况正常!” 即使唯一提交给线程池的Runnable引发异常。任何线索这里发生了什么? 谢谢! 问题答案: 提交Runnable
要并行或异步运行一些东西,我可以使用ExecutorService: