我有一个相当复杂的应用程序,我正在尝试为Android手机创建。我有一个使用Java Process Builder的类和一些私有类来读取输入和输出流。
当我尝试ping的IP由于进程卡住而没有响应线程锁时,执行程序服务在2分钟后决定关闭。这样可以避免整个应用程序锁定,但两个流永远不会关闭,并且流的线程保持打开状态。
知道如何杀死流线程吗?
class StreamGobbler extends Thread {
InputStream is;
String type;
StreamGobbler(InputStream is, String type) {
this.is = is;
this.type = type;
}
public void run() {
InputStreamReader isr = new InputStreamReader(is);
try {
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null){
System.out.println(type + ">" + line);
}
} catch (IOException e) {
LogWriter.getInstance().writeToLogFile(e);
}finally{
try {
if(is != null){
is.close();
}
if(isr != null){
isr.close();
}
} catch (IOException e) {
LogWriter.getInstance().writeToLogFile(e);
}
}
}
public void kill() {
Thread.currentThread().interrupt();
}
}
public class PingRunner implements Callable<Double>{
private String pingVal;
private int exitVal;
private double laten;
private String ipAddress;
public PingRunner(String ipAddress) {
pingVal = "";
exitVal = -1;
laten = -1;
this.ipAddress = ipAddress;
}
@Override
public Double call() throws Exception {
List<String> commands = new ArrayList<String>();
commands.add("ping");
commands.add("-c");
commands.add("5");
commands.add(ipAddress);
try {
this.doCommand(commands);
} catch (IOException e) {
LogWriter.getInstance().writeToLogFile(e);
}
return laten;
}
private void doCommand(List<String> command) throws IOException{
ProcessBuilder pb = new ProcessBuilder(command);
Process process = pb.start();
// any error message?
StreamGobbler errorGobbler = new StreamGobbler(
process.getErrorStream(), "ERROR");
// any output?
OutputStreamGobbler outputGobbler = new OutputStreamGobbler(
process.getInputStream(), "OUTPUT");
// kick them off
errorGobbler.start();
outputGobbler.start();
// read the output from the command
try {
exitVal = process.waitFor();
//Sleep for 10 secs to try to clear the buffer
Thread.sleep(10000);
//pingVal = echo.toString();
if(exitVal == 0 && !pingVal.isEmpty()){
//System.out.println("PING STATS: "+pingVal);
try{
pingVal = pingVal.substring(pingVal.lastIndexOf("rtt min/avg/max/mdev"));
pingVal = pingVal.substring(23);
pingVal = pingVal.substring(pingVal.indexOf("/")+1);
laten = Double.parseDouble(pingVal.substring(0,pingVal.indexOf("/")));
}catch (IndexOutOfBoundsException e){
System.out.println("PING VAL: "+ pingVal);
LogWriter.getInstance().writeToLogFile(e);
}
}
} catch (InterruptedException e) {
LogWriter.getInstance().writeToLogFile(e);
errorGobbler.kill();
outputGobbler.kill();
}finally{
errorGobbler = null;
outputGobbler = null;
}
System.out.println("ExitValue: " + exitVal);
}
在我的主要课程中,我有这种方法:
protected void ping() {
laten = -1;
serverIP = serverIPs.get(testIndex % 3);
PingRunner pRunner = new PingRunner(serverIP);
Set<Callable<Double>> runner = new HashSet<Callable<Double>>();
runner.add(pRunner);
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
laten = executor.submit(pRunner).get(2, TimeUnit.MINUTES);
executor.shutdown();
} catch (InterruptedException e) {
LogWriter.getInstance().writeToLogFile(e);
} catch (ExecutionException e) {
LogWriter.getInstance().writeToLogFile(e);
} catch (CancellationException e) {
pRunner.kill();
executor.shutdown();
LogWriter.getInstance().writeToLogFile(e);
LogWriter.getInstance().writeToLogFile(
"ERROR: Unable to ping server: " + serverIP);
} catch (TimeoutException e) {
pRunner.kill();
executor.shutdown();
LogWriter.getInstance().writeToLogFile(e);
LogWriter.getInstance().writeToLogFile(
"ERROR: Unable to ping server: " + serverIP);
} finally {
executor = null;
System.gc();
}
答案 0 :(得分:0)
知道如何杀死流线程吗?
不确定发生了什么,但我看到的一个错误是:
public void kill() {
Thread.currentThread().interrupt();
}
这是打断调用者线程,而不是gobbler线程。那应该是:
public void kill() {
// kill the gobbler thread
interrupt();
}
这是正确的,因为StreamGobbler
扩展了Thread
。与往常一样,建议您implements Runnable
然后根据需要设置private Thread field
。然后你会做thread.interrupt();
。
此外,您没有正确关闭流。通常,当我将一个流包装在另一个流中时,我将包装的流设置为null
。此外,您还没有关闭br
BufferedReader
。代码应该是:
InputStreamReader isr = new InputStreamReader(is);
is = null;
BufferedReader br = null;
try {
br = new BufferedReader(isr);
isr = null;
String line = null;
...
} finally {
// IOException catches not listed
if(br != null){
br.close();
}
if(isr != null){
isr.close();
}
if(is != null){
is.close();
}
}
我是拥有org.apache.commons.io.IOUtils
方法的closeQuietly(...)
软件包的忠实粉丝,该方法将finally块转换为:
IOUtils.closeQuietly(br);
IOUtils.closeQuietly(isr);
IOUtils.closeQuietly(is);