目的: 数据冗余备份,提高稳定性
自己实现
参考> https://blog.csdn.net/fanrey123/article/details/84215112
Develop a parallel multithreaded program (in C using Pthreads, or in Java) that implements the Unix tee command, which is invoked as follows:
tee filename
The command reads the standard input and writes it to both the standard output and to the file filename. Your parallel tee program should have three threads: one for reading standard input, one for writing to standard output, and one for writing to file filename.
思考》
怎么判断文件读到结尾
写线程如何停下来
队列被读两次 信号量的控制
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Lock;
public class TeeTest {
private static List<String> queue = new ArrayList<>();
private static boolean EOF = false;
public static Lock lock = new ReentrantLock();
public static Condition condOutput = lock.newCondition();
public static Condition condReader = lock.newCondition();
public static int counterFile = 0;
public static int counterConsole = 0;
public static void main(String[] args) {
args = new String[2];
args[0] = "C:\LCT\3.txt";
args[1] = "C:\LCT\tmp.txt";
if (args == null || args.length != 2) {
System.out.println("java Tee <input file> <output file>");
System.exit(1);
}
FileWriterThread fThread = new FileWriterThread(args[1]);
ConsoleWriterThread cThread = new ConsoleWriterThread();
fThread.start();
cThread.start();
ReaderThread rThread = new ReaderThread(args[0]);
rThread.start();
}
static class ReaderThread extends Thread {
private String fileName;
public ReaderThread(String fileName) {
this.fileName = fileName;
}
public void run() {
BufferedReader in;
try {
in = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
String line;
while ((line = in.readLine()) != null) {
lock.lock();
queue.add(line);
condOutput.signalAll();
condReader.await();
queue.clear();
lock.unlock();
}
in.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
EOF = true;
lock.lock();
condOutput.signalAll();
lock.unlock();
}
}
}
static class FileWriterThread extends Thread {
private FileOutputStream out;
private PrintWriter pw;
public FileWriterThread(String fileName) {
try {
out = new FileOutputStream(new File(fileName));
pw = new PrintWriter(out);
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
do {
lock.lock();
if (queue.isEmpty() || counterFile == 1) {
try {
condOutput.await();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
for (Iterator<String> iter = queue.iterator(); iter.hasNext(); ) {
String line = iter.next();
pw.println(line);
try {
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
counterFile++;
if (counterFile == 1 && counterConsole == 1) {
queue.clear();
counterFile = 0;
counterConsole = 0;
condReader.signal();
}
lock.unlock();
} while (!EOF);
try {
pw.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
static class ConsoleWriterThread extends Thread {
public ConsoleWriterThread() {
}
public void run() {
do {
lock.lock();
if (queue.isEmpty() || counterConsole == 1) {
try {
condOutput.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (Iterator<String> iter = queue.iterator(); iter.hasNext(); ) {
System.out.println(iter.next());
}
counterConsole++;
if (counterFile == 1 && counterConsole == 1) {
queue.clear();
counterFile = 0;
counterConsole = 0;
condReader.signal();
}
lock.unlock();
} while (!EOF);
}
}
}