赞
踩
对于我而言,我更喜欢为要写入的通道提供一个OutputStream,而不是从它提供给我的InputStream中读取。
我将定义如下内容:
protected class MyOutputStream extends OutputStream {
private StringBuilder stringBuilder = new StringBuilder();
private Object lock;
public MyOutputStream(Object lock) {
this.lock = lock;
}
@Override
public void write(int b) throws IOException {
this.stringBuilder.append(b);
if (b == '\n') {
this.parseOutput();
}
}
@Override
public void write(byte[] b) throws IOException {
String str = new String(b);
this.stringBuilder.append(str);
if (str.contains("\n")) {
this.parseOutput();
}
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
String str = new String(b, off, len);
this.stringBuilder.append(str);
if (str.contains("\n")) {
this.parseOutput();
}
}
@Override
public void flush() throws IOException {
}
@Override
public void close() throws IOException {
LOGGER.info("My output stream has closed");
}
private void parseOutput() throws IOException {
// we split the text but we make sure not to drop the empty strings or the trailing char
String[] lines = this.stringBuilder.toString().split("\n", -1);
int num = 0;
int last = lines.length - 1;
String trunkated = null;
// synchronize the writing
synchronized (this.lock) {
for (String line : lines) {
// Dont treat the trunkated last line
if (num == last && line.length() > 0) {
trunkated = line;
break;
}
// write a full line
System.out.print(line);
num++;
}
}
// flush the buffer and keep the last trunkated line
this.stringBuilder.setLength(0);
if (trunkated != null) {
this.stringBuilder.append(trunkated);
}
}
}
因此用法如下:
ArrayList channels = new ArrayList();
Object lock = new Object();
ChannelExec channel;
channel = (ChannelExec)session1.openChannel("exec");
channel.setCommand("echo one && sleep 2 && echo two && sleep 2 && echo three");
channel.setOutputStream(new MyOutputStream(lock));
channel.connect();
channels.add(channel);
channel = (ChannelExec)session2.openChannel("exec");
channel.setCommand("sleep 1 && echo eins && sleep 2 && echo zwei && sleep 2 && echo drei");
channel.setOutputStream(new MyOutputStream(lock));
channel.connect();
channels.add(channel);
for (ChannelExec channel : channels) {
while (!channel.isClosed()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
好处是,您可以受益于Jsch通道中已经存在的多线程,然后避免了泛滥日志的问题,该问题不会让其他日志被打印。 使用不同的流类处理每个日志也更加容易和清晰。 在获得完整行之前,StringBuilder是累积字符的好方法。
还需要注意的是,一次编写整行避免了每个char调用一个函数,并且避免了将所写char的数量与系统的server.getFontColor()。toString()相乘。
确保正确锁定,我编写的代码未经测试。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。