gpt4 book ai didi

java - Java中的线程间通信

转载 作者:太空宇宙 更新时间:2023-11-04 13:52:18 26 4
gpt4 key购买 nike

我有两个 Java 线程需要相互通信,但我不确定我是否以正确的方式处理此问题。

基本是这样的:我有一个线程,“运行程序”,它将通过使用 Apache exec 库调用命令行来启动长时间运行的进程。另一个线程“监视器”将定期监视并报告系统的状态。

其中一部分涉及返回运行程序进程从标准输出获取的行。目前,运行程序和监视器作为单独的线程运行。监视器具有对运行程序的引用,并且可以通过调用运行程序的“get stdout”方法来访问(到目前为止)收集的输出。

这似乎工作正常,但整个设置对我来说似乎不太好。部分原因是,我担心这个实现不是线程安全的,尽管我什至不确定如何测试它。我已经有一段时间没有进行多线程编程了,所以我想知道是否有更好/更干净的方法来完成我想做的事情。代码看起来像这样:

public class Runner implements Callable<String> 
{
private ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
private ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
public String getStdOutLines()
{
return new String(outputStream.toByteArray());
}
public String getStdErrLines()
{
return new String(errorStream.toByteArray());
}

@Override
public String call() throws Exception
{
/*
Use apache exec to begin long-running process.
stdout and stderr are written to two local members (outputStream and errorStream).
This is done by the apache exec library.
*/
PumpStreamHandler streamHandler = new PumpStreamHandler(this.outputStream, this.errorStream);
DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
executor.setStreamHandler(streamHandler);
CommandLine cli = //Details not important here.
executor.execute(cli, resultHandler);
resultHandler.waitFor();
String resultsString = generateFinalResultString(outputStream, errorStream); //implementation details of this not important here.
return resultsString; /*some string calculated after the process has completed.*/
}
}

public class Monitor implements Runnable
{
private Runner runner;

public void setRunner(Runner r)
{
this.runner = r;
}

@Override
public void run()
{
try
{
while (!Thread.currentThread().interrupted())
{
//Call the functions on the other thread to get the stdout and stderr
commandStdOut = this.runner.getStdOutLines();
commandStdErr = this.runner.getStdErrLines();
doSendMonitoringMessage(commandStdOut, commandStdErr);
Thread.sleep(SOME_DELAY);
}
}
catch(InterruptedException e)
{
System.out.println("Monitor is shutting down");
}
}
}

public class ExecuteAllThis
{
public void doTheStuff()
{
System.out.println("begining...");
Runner runner = new Runner();
Monitor monitor = new Monitor();

monitor.setRunner(runner);
ExecutorService xservice = Executors.newFixedThreadpool(2);
xservice.execute(monitor);
Future<String> runnerFuture = xservice.submit(runner);
String result = runnerFuture.get(0);
System.out.println("result is: "+result);
}

编辑:我添加了一些关于如何调用写入 stdout 和 stderr 字符串的长时间运行进程的详细信息,因为这比我最初意识到的更相关。

最佳答案

你的实现很好。

但是,理论上,变量outputStreamerrorStream应该是volatile ,否则监视器线程理论上可能无法获取最新更新。

使用volatile的另一个原因对于共享变量,一般情况下,是为了防止读取损坏的状态。但这个原因并不适用于此,因为 String是不可变的。

另一个建议,如果您不确定,请使用旧的 synchronized 。可能比 volatile 慢一点,但这通常不是问题;当然不是你的情况。

关于java - Java中的线程间通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30175477/

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