尝试使用Java中的PipedInputStream和PipedOutputStream实现线程同步时遇到问题。
有三个线程T1,T2,T3可以同时编辑名为toto.txt的文件。 toto.txt的文件内容类似于:
T1 : 1 T2 : 1 T3 : 1 T1 : 2 T2 : 2 T3 : 2 T1 : 3 T2 : 3 T3 : 3 ....
我的想法是:每个线程只有在键变量key = true时才能访问toto.txt。编辑文件后,将A键密钥内容写入连接到PipedOutputStream的pipedInputStream。线程B从PipedOutStream读取密钥,如果key = true,B可以访问编辑文件。有一个可以写入文件的起始线程,另一个线程首先等待该键 - >写入文件 - >将密钥写入管道。如果有3个螺纹,则连接3个管道:T1-T2,T2-T3,T3-T1。
我的代码线程
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class threadFlux implements Runnable {
public String _threadName;
public boolean _key;
public boolean _stratingThread;
public int _count;
public int _maxCount;
public String _fileName;
public DataInputStream _is;
public DataOutputStream _os;
public threadFlux(String threadName, String fileName, boolean starting, int maxCount) {
this._threadName = threadName;
this._maxCount = maxCount;
this._count = 1;
this._fileName = fileName;
this._stratingThread = starting;
this._key = (starting == true);
}
@Override
public void run() {
while (this._count <= this._maxCount) {
if (this._stratingThread == true) {
try {
/* starting thread write to file */
System.out.println("startint thread");
System.out.println(this._threadName + ": " + this._count);
this.writeToFile(this._threadName + ": " + this._count + "\n");
this._count++;
/* write key to pipe */
this.writeKeyToPipe(this._key);
System.out.println("key written");
/* set key = false */
this._key = false;
this._stratingThread = false;
} catch (IOException ex) {
Logger.getLogger(threadFlux.class.getName()).log(Level.SEVERE, null, ex);
}
} else {
try {
/* read key from pipe */
System.out.println(this._threadName + " Clef " + this._key);
this._key = this.readKeyFromPipe();
System.out.println(this._threadName + " Clef " + this._key);
/* write key to pipe */
System.out.println(this._threadName + ": " + this._count);
this.writeToFile(this._threadName + ": " + this._count + "\n");
this._count++;
/* write key to pipe for another thread */
this.writeKeyToPipe(this._key);
this._key = false;
} catch (IOException ex) {
Logger.getLogger(threadFlux.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
System.out.println(this._threadName + " finish!");
}
public void setPipedStream(PipedOutputStream pos, PipedInputStream pis) throws IOException {
this._os = new DataOutputStream(new BufferedOutputStream(pos));
this._is = new DataInputStream(new BufferedInputStream(pis));
}
private void writeToFile(String string) throws IOException {
File file = new File(this._fileName);
//if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
//true = append file
FileWriter fileWritter = new FileWriter(file.getName(), true);
try (BufferedWriter bufferWritter = new BufferedWriter(fileWritter)) {
bufferWritter.write(string);
bufferWritter.close();
}
}
private void writeKeyToPipe(boolean _key) throws IOException {
this._os.writeBoolean(_key);
}
private boolean readKeyFromPipe() throws IOException {
return this._is.readBoolean();
}
}
我的主要节目
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Test {
public static void main(String[] args) {
try {
// TODO code application logic here
threadFlux runnableThread1 = new threadFlux("T1", "toto.txt", true, 3);
threadFlux runnableThread2 = new threadFlux("T2", "toto.txt", false, 3);
threadFlux runnableThread3 = new threadFlux("T3", "toto.txt", false, 3);
PipedOutputStream pos1 = new PipedOutputStream();
PipedOutputStream pos2 = new PipedOutputStream();
PipedOutputStream pos3 = new PipedOutputStream();
PipedInputStream pis2 = new PipedInputStream(pos1);
PipedInputStream pis1 = new PipedInputStream(pos3);
PipedInputStream pis3 = new PipedInputStream(pos2);
runnableThread1.setPipedStream(pos1, pis1);
runnableThread2.setPipedStream(pos2, pis2);
runnableThread3.setPipedStream(pos3, pis3);
Thread thread1 = new Thread(runnableThread1);
Thread thread2 = new Thread(runnableThread2);
Thread thread3 = new Thread(runnableThread3);
thread1.start();
thread2.start();
thread3.start();
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} finally {
}
}
}
当我运行那些代码时出现的问题:在起始线程写入文件并将密钥写入PipedOutputStream之后它被阻止。
感谢您的帮助
答案 0 :(得分:0)
PipedOutputStream有一个固定的缓冲区,上次我看了4k。当它在写入时填充它,直到读取线程读取某些东西。所以你的阅读线程没有阅读。
不要这样做。线程之间的I / O管道基本上是不必要的。您不需要像这样移动数据。寻找另一种设计。