gpt4 book ai didi

java - 在java中以循环方式运行线程

转载 作者:行者123 更新时间:2023-12-01 17:21:41 25 4
gpt4 key购买 nike

我是java中多线程和同步的新手。我正在尝试实现一项任务,其中给我 5 个文件,每个文件将由一个特定线程读取。每个线程都应该从文件中读取一行,然后将执行转发到下一个线程,依此类推。当所有 5 个线程都读取第一行时,然后再次从线程 1 开始运行第 1 行。文件 1 的 2 等等。

    Thread ReadThread1 = new Thread(new ReadFile(0));
Thread ReadThread2 = new Thread(new ReadFile(1));
Thread ReadThread3 = new Thread(new ReadFile(2));
Thread ReadThread4 = new Thread(new ReadFile(3));
Thread ReadThread5 = new Thread(new ReadFile(4));

// starting all the threads
ReadThread1.start();
ReadThread2.start();
ReadThread3.start();
ReadThread4.start();
ReadThread5.start();

在ReadFile(它实现了Runnable)中,在run方法中,我试图在bufferreader对象上进行同步。

        BufferedReader br = null;

String sCurrentLine;
String filename="Source/"+files[fileno];
br = new BufferedReader(new FileReader(filename));

synchronized(br)
{

while ((sCurrentLine = br.readLine()) != null) {
int f=fileno+1;
System.out.print("File No."+f);
System.out.println("-->"+sCurrentLine);
br.notifyAll();
// some thing needs to be dine here i guess
}}

需要帮助

最佳答案

虽然这不是使用多线程的理想场景,但由于这是作业,我将提供一个可行的解决方案。线程将按顺序执行,有几点需要注意:

  1. 当前线程无法继续读取文件中的行,除非其紧邻的前一个线程已完成(因为它们应该以循环方式读取)。
  2. 当前线程读取完该行后,必须通知另一个线程,否则该线程将永远等待。

我已经使用临时包中的一些文件测试了此代码,它能够以循环方式读取行。我相信Phaser也可以用来解决这个问题。

    public class FileReaderRoundRobinNew {
public Object[] locks;

private static class LinePrinterJob implements Runnable {
private final Object currentLock;


private final Object nextLock;
BufferedReader bufferedReader = null;

public LinePrinterJob(String fileToRead, Object currentLock, Object nextLock) {
this.currentLock = currentLock;
this.nextLock = nextLock;
try {
this.bufferedReader = new BufferedReader(new FileReader(fileToRead));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}

@Override
public void run() {
/*
* Few points to be noted:
* 1. Current thread cannot move ahead to read the line in the file until and unless its immediately previous thread is done as they are supposed to read in round-robin fashion.
* 2. After current thread is done reading the line it must notify the other thread else that thread will wait forever.
* */
String currentLine;
synchronized(currentLock) {
try {
while ( (currentLine = bufferedReader.readLine()) != null) {
try {
currentLock.wait();
System.out.println(currentLine);
}
catch(InterruptedException e) {}
synchronized(nextLock) {
nextLock.notify();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
synchronized(nextLock) {
nextLock.notify(); /// Ensures all threads exit at the end
}
}
}

public FileReaderRoundRobinNew(int numberOfFilesToRead) {
locks = new Object[numberOfFilesToRead];
int i;
String fileLocation = "src/temp/";
//Initialize lock instances in array.
for(i = 0; i < numberOfFilesToRead; ++i) locks[i] = new Object();
//Create threads
int j;
for(j=0; j<(numberOfFilesToRead-1); j++ ){
Thread linePrinterThread = new Thread(new LinePrinterJob(fileLocation + "Temp" + j,locks[j],locks[j+1]));
linePrinterThread.start();
}
Thread lastLinePrinterThread = new Thread(new LinePrinterJob(fileLocation + "Temp" + j,locks[numberOfFilesToRead-1],locks[0]));
lastLinePrinterThread.start();
}

public void startPrinting() {
synchronized (locks[0]) {
locks[0].notify();
}
}

public static void main(String[] args) {
FileReaderRoundRobinNew fileReaderRoundRobin = new FileReaderRoundRobinNew(4);
fileReaderRoundRobin.startPrinting();
}
}

如果唯一的目标是以循环方式读取文件而不是严格按照相同的顺序,那么我们也可以使用 Phaser。在这种情况下,读取文件的顺序并不总是相同,例如,如果我们有四个文件(F1、F2、F3 和 F4),那么在第一阶段它可以将它们读取为 F1-F2-F3-F4,但在下一个阶段它可以将它们读取为 F2-F1-F4-F3。为了完成,我仍然放置此解决方案。

public class FileReaderRoundRobinUsingPhaser {

final List<Runnable> tasks = new ArrayList<>();
final int numberOfLinesToRead;

private static class LinePrinterJob implements Runnable {
private BufferedReader bufferedReader;

public LinePrinterJob(BufferedReader bufferedReader) {
this.bufferedReader = bufferedReader;
}

@Override
public void run() {
String currentLine;
try {
currentLine = bufferedReader.readLine();
System.out.println(currentLine);
} catch (IOException e) {
e.printStackTrace();
}
}
}

public FileReaderRoundRobinUsingPhaser(int numberOfFilesToRead, int numberOfLinesToRead) {
this.numberOfLinesToRead = numberOfLinesToRead;
String fileLocation = "src/temp/";
for(int j=0; j<(numberOfFilesToRead-1); j++ ){
try {
tasks.add(new LinePrinterJob(new BufferedReader(new FileReader(fileLocation + "Temp" + j))));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}

public void startPrinting( ) {
final Phaser phaser = new Phaser(1){
@Override
protected boolean onAdvance(int phase, int registeredParties) {
System.out.println("Phase Number: " + phase +" Registeres parties: " + getRegisteredParties() + " Arrived: " + getArrivedParties());
return ( phase >= numberOfLinesToRead || registeredParties == 0);
}
};

for(Runnable task : tasks) {
phaser.register();
new Thread(() -> {
do {
phaser.arriveAndAwaitAdvance();
task.run();
} while(!phaser.isTerminated());
}).start();
}
phaser.arriveAndDeregister();
}

public static void main(String[] args) {
FileReaderRoundRobinUsingPhaser fileReaderRoundRobin = new FileReaderRoundRobinUsingPhaser(4, 4);
fileReaderRoundRobin.startPrinting();
// Files will be accessed in round robin fashion but not exactly in same order always. For example it can read 4 files as 1234 then 1342 or 1243 etc.
}

}

上面的例子可以根据具体要求进行修改。这里 FileReaderRoundRobinUsingPhaser 的构造函数获取文件数和从每个文件读取的行数。还需要考虑边界条件。

关于java - 在java中以循环方式运行线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18314852/

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