gpt4 book ai didi

java - 使用没有连接方法的多线程并行读取三个文件并按顺序将内容写入其他文件

转载 作者:行者123 更新时间:2023-11-30 09:06:51 25 4
gpt4 key购买 nike

我上次面试有一个问题,都是关于多线程的,面试官让我写一个程序,首先使用多线程将三个文件(F1,F2,F3)的内容写入一个新文件F4线程应该读取第一个文件,第二个线程应该读取第二个文件,所以文件 F4 应该首先包含 F1 的内容,然后是 F2 的内容,等等。我尽力而为,但我无法确保线程写入文件的顺序是第一个线程写入第一个文件内容,然后是第二个线程等等。

一个奇怪的情况是我不应该使用连接方法。

我写了下面的程序,但是无法得到写入文件的逻辑来确保内容是有序的,请帮助我。

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;


public class ThreadTest implements Runnable {

final static String FILE_NAME1 = "C:\\Temp\\input1.txt";
final static String FILE_NAME2 = "C:\\Temp\\input2.txt";
final static String FILE_NAME3 = "C:\\Temp\\input3.txt";
final static String OUTPUT_FILE_NAME = "C:\\Temp\\output.txt";
final static Charset ENCODING = StandardCharsets.UTF_8;
List<String> readTextFile1;
List<String> readTextFile2;
List<String> readTextFile3;

@Override
public void run() {

Thread t=Thread.currentThread();
if(t.getName().equals("t1"))
{
System.out.println("Started"+ t.getName());
try {
readTextFile1 = readTextFile(FILE_NAME1);

writeTextFile(readTextFile1,OUTPUT_FILE_NAME);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Ended"+ t.getName());
}
if(t.getName().equals("t2"))
{
System.out.println("Started"+ t.getName());
try {
readTextFile2 = readTextFile(FILE_NAME2);

writeTextFile(readTextFile2,OUTPUT_FILE_NAME);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Ended"+ t.getName());

}
if(t.getName().equals("t3"))
{
System.out.println("Started"+ t.getName());

try {
readTextFile3 = readTextFile(FILE_NAME3);

writeTextFile(readTextFile3,OUTPUT_FILE_NAME);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Ended"+ t.getName());
}


}


List<String> readTextFile(String fileName) throws IOException {
Path path = Paths.get(fileName);
return Files.readAllLines(path, ENCODING);
}

void writeTextFile(List<String> strLines, String fileName) throws IOException {
synchronized (fileName) {
Path path = Paths.get(fileName);
Files.write(path, strLines, ENCODING,StandardOpenOption.APPEND);
}


}
public static void main(String[] args) throws InterruptedException {

ThreadTest tt1=new ThreadTest();
ThreadTest tt2=new ThreadTest();
ThreadTest tt3=new ThreadTest();
Thread t1=new Thread(tt1, "t1");
Thread t2=new Thread(tt2, "t2");
Thread t3=new Thread(tt3, "t3");

t1.start();
t2.start();
t3.start();
System.out.println("Finished");
}

}

最佳答案

使用信号量有点像使用连接方法,但不调用连接方法。它可以用一个 volatile 和一个 while 循环代替,就像@anirban 描述的那样(见下面注释掉的行):

import java.io.ByteArrayOutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class Read3Write1 implements Runnable {

public static void main(String[] args) {

ExecutorService tp = Executors.newCachedThreadPool();
Read3Write1[] readers = new Read3Write1[3];
// start threads in reverse order to show it does not matter to end-result.
for (int i = 2; i > -1; i--) {
tp.execute(readers[i] = new Read3Write1("FileName dummy " + i + System.getProperty("line.separator")));
}
ByteArrayOutputStream bout = new ByteArrayOutputStream();
for (int i = 0; i < 3; i++) {
try {
bout.write(readers[i].getFileContents());
} catch (Exception e) {
e.printStackTrace();
break;
}
}
System.out.println(new String(bout.toByteArray()));
tp.shutdownNow();
}

private final String fileName;
private final Semaphore done = new Semaphore(0);
// private volatile boolean done;
private volatile byte[] fileContents;

public Read3Write1(String fileName) {
super();
this.fileName = fileName;
}

public byte[] getFileContents() {

try {
done.acquire();
} catch (Exception e) {
e.printStackTrace();
return null;
}
// while (!done) { Thread.yield(); }
return fileContents;
}

@Override
public void run() {

try {
fileContents = readFile();
} catch (Exception e) {
e.printStackTrace();
} finally {
done.release();
// done = true;
}
}

private byte[] readFile() {
return fileName.getBytes();
}

}

此技术的一个用例是需要从安装在缓慢且不稳定的网络上的不同网络驱动器读取许多文件。与同时读取所有文件并将内容(的副本)存储到(快速)本地磁盘相比,一个一个地读取文件所花费的时间要多 N 倍。

关于java - 使用没有连接方法的多线程并行读取三个文件并按顺序将内容写入其他文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24264167/

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