关于Java线程超时退出的问题.
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Java线程超时退出的问题.相关的知识,希望对你有一定的参考价值。
小弟近来有个任务是这样的,JAVA主程序中开启一个线程,我希望在一定的时间范围内 如果这个线程还没有运行完,就采取一些方法主动将他干掉,试了网上很多的方法都没有用,顶多是能抛出个异常,通知一下超时,但是线程还是在继续运行。
请教各位大虾们该怎么解决啊!!!
就没有哪个神人,能解决这个问题么. 我开的这个线程可能是要和别的程序进行交互,交互过程中可能会卡死,所以我才想能不能采取一些方法将他主动停掉,你们介绍的方法都不行...
结贴了吧.
比如在出现异常的地方:
threadA.interrupt();
而threadA的run方法中:
public void run()
while(true)
try
....
catch (InterruptedException)
break; //这样是可以的,如果没有break或者修改为continue则不行
也可以将这个放在while循环之外。
public void run()
try
while(true)
....
catch (InterruptedException)
....
本回答被提问者采纳 参考技术B class AutoCloseThread implements Runnable
private int limit;//限制
private Timer timer=new Timer();
@Override
public void run()
TimerTask task=new TimerTask()
@Override
public void run()
limit++;
if(limit>50) timer.cancel();
;
timer.schedule(task, 0, 1000);
timer.schedule(task, 0);
shaoyunlu 2010-7-13 17:31:19
timer.schedule(task, 0, 1000);
timer.schedule(task, 0);
这两个 要一起写?
军 2010-7-13 17:44:31
不是
军 2010-7-13 17:44:43
timer.schedule(task, 0, 1000);
timer.schedule(“webservice”, 0);
参考资料:还有其他问题的话,给我发百度消息
参考技术C java.util.concurrent.Future默认实现java.util.concurrent.FutureTask
你去查一下有关这个类的用法吧,他能满足你的要求。
或者java.util.concurrent.ExecutorService这个线程池也行。 参考技术D 线程中run()写法类似下面
public void run()
....
while(t<毫秒)
{
。。。。。
}//程序结束
}
在while里设置线程停止条件,我这个是判断时间。也可以设置一个标识,例如:
public void run()
boolean isEnd = false;
.....
while(isEnd == false)
if(....)
isEnd = true;
break;
......
有空看看《JAVA多线程设计》,好书,结合设计模式讲的JAVA多线程。浅显易懂
===============补充你的补充问题==============
你既然说是想主动停掉。这个意思已经很明显了,你现在的问题只是,你在代码设计思路上陷入死循环了。
所谓主动停掉就是到了指定的条件,程序自然死亡结束。你要做的就是写一个销毁方法,将线程结束的所有操作都写在里面,包括你调用或交互的其它程序结束方法。然后在指定条件下调用这个销毁操作。我不知道我说的明白不?
[Java]_[初级]_[如何调用外部命令获取输出并设置它的超时退出]
场景
-
在开发
Java
程序的时候,有时候需要执行外部命令以获取特定信息,但是外部命令执行可能由于某些原因(比如CPU,内存占用高后延迟执行)比正常执行的时间要长,有时候甚至挂起阻塞了Java
线程的执行。那么我们如何使用标准库来完成调用外部命令的超时时间设置? -
还有基本的问题,如何读取启动进程的输出?
说明
Java
使用ProcessBuilder
来创建外部命令的进程,并使用方法command
来异步执行外部命令.
ProcessBuilder ps = new ProcessBuilder();
ps.command(命令路径);
Process process = ps.start();
- 之后通过对象
process
的process.getInputStream()
获取一个连接到进程输出的输入流,这个输入流使用管道的方式连接到进程的标准输出上,所以读取这个输入流就可以读取这个进程的输出。通过读取这个进程的输出并存储到StringBuffer
里.
StringBuffer line = new StringBuffer();
String temp = "";
try(BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()))){
while ((temp = in.readLine()) != null)
line.append(temp);
exitCode = process.waitFor();
}catch (Exception e){
e.printStackTrace();
}finally {
if(exitCode != 0)
process.destroy();
}
- 为了外部进程的超时判断,那么外部进程肯定需要额外的线程进行运行和读取输出,使用了线程池
ThreadPoolExecutor
来执行任务会比较好, 避免频繁的创建线程。而Executor.submit
返回了一个Future
对象,这个对象是并发包里的类,主要是可以异步获取工作线程返回的值。通过这个Future
对象可以获取到外部进程执行的结果,它还有设置延时等待的get
方法正好合适。
String java.util.concurrent.Future.get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
- 在使用
Future
的get
获取返回结果时,可以通过抛出的超时异常来销毁未结束的进程。关于Future
的介绍可以参考课程JDK8-Java8-JavaSE8新特性和增强功能.
TaskCallable callable = new TaskCallable();
Future<String> handler = executor.submit(callable);
String message = "";
try {
message = handler.get(kGenWaitTimeoutSeconds, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
callable.cancelProcess();
}
- 在以下的例子里我把调用外部命令封装到一个
Callable<String>
对象里,方便Executor.submit
调用.
例子
package com;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Test;
public class ProcessExecTest {
private ThreadPoolExecutor executor;
private BlockingQueue<Runnable>queue;
private static int queueSize = 1024;
private static int threadKeepAliveTime = 120;
private static int kGenWaitTimeoutSeconds = 10;
public static void print(String key,String str){
System.out.println(key+": "+str);
}
public ProcessExecTest(){
int processors = Runtime.getRuntime().availableProcessors();
// 常规任务
queue = new LinkedBlockingQueue<Runnable>(queueSize);
executor = new ThreadPoolExecutor(processors,processors,
threadKeepAliveTime,TimeUnit.SECONDS, queue);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
}
@Test
public void testProcess(){
TaskCallable callable = new TaskCallable();
Future<String> handler = executor.submit(callable);
String message = "";
try {
message = handler.get(kGenWaitTimeoutSeconds, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
callable.cancelProcess();
}
print("message",message);
}
public static class TaskCallable implements Callable<String>{
private Process process;
private int exitCode = 1;
public void cancelProcess(){
if(process != null && exitCode != 0)
process.destroy();
}
public TaskCallable(){
}
@Override
public String call() throws Exception {
File dir = new File("C:\\\\Windows\\\\System32");
ProcessBuilder ps = new ProcessBuilder();
ps.directory(dir);
Path dirPath = dir.toPath();
Path exePath = dirPath.resolve("cmd.exe");
ps.command(exePath.toString(),"/C","echo tobey");
process = ps.start();
if(process == null)
return "";
StringBuffer line = new StringBuffer();
String temp = "";
try(BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()))){
while ((temp = in.readLine()) != null)
line.append(temp);
exitCode = process.waitFor();
}catch (Exception e){
e.printStackTrace();
}finally {
if(exitCode != 0)
process.destroy();
}
return (exitCode == 0)?line.toString():"";
}
}
}
输出
message: tobey
参考
以上是关于关于Java线程超时退出的问题.的主要内容,如果未能解决你的问题,请参考以下文章
关于java.sql.SQLRecoverableException: Closed Connection异常的解决方案(转)
[Java]_[初级]_[如何调用外部命令获取输出并设置它的超时退出]