gpt4 book ai didi

java - Open Stream 和 CancellationException 导致线程锁

转载 作者:行者123 更新时间:2023-11-29 09:00:45 24 4
gpt4 key购买 nike

我有一个相当复杂的应用程序,我正在尝试为 Android 手机创建它。我有一个类使用 Java Process Builder 和一些私有(private)类来读取输入和输出流。

有时,当我尝试 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();
}

最佳答案

Any idea how to kill the stream threads?

不确定发生了什么,但我看到的一个错误是:

public void kill() {
Thread.currentThread().interrupt();
}

那是中断调用者 线程,而不是 gobbler 线程。那应该是:

public void kill() {
// kill the gobbler thread
interrupt();
}

这是真的,因为 StreamGobbler 扩展了 Thread。与往常一样,建议您实现 Runnable,然后在必要时拥有一个私有(private) Thread 字段。然后你会做类似 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 block 进入:

IOUtils.closeQuietly(br);
IOUtils.closeQuietly(isr);
IOUtils.closeQuietly(is);

关于java - Open Stream 和 CancellationException 导致线程锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17664265/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com