我创建了两个线程并修改了run函数,以便一个线程读取一行,另一个线程将同一行写入新文件。这种情况发生,直到整个文件被复制。我得到的问题是,即使我已经使用变量来控制线程逐个执行,但线程执行不均匀,即一个线程执行多次,然后控件传输。我附上代码的任何解决方案。我是java新手,因为它只用于类分配,所以代码可能不是最优化的。
public class thread1 extends Thread {
//To create producer and consumer as threads
//Shared variable
public static int x = 0;//checks if all lines are read
public static String line; /holds lines from file
public static int j = 0;//variable to switch between threads based upon its value
public thread1(String threadName) { //Constuctor
super(threadName); //Call to constructor of Thread class
}
public void run() {
while (x != -1)
{
if (Thread.currentThread().getName().contains("Reader")) {
if (x != -1&&j==0)
{
j=1;
String fileName = "d:/salfar.txt";
try {
// FileReader reads text files in the default encoding.
FileReader fileReader =
new FileReader(fileName);
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader =
new BufferedReader(fileReader);
for (int check = 0; check <= x; check++) {
line = bufferedReader.readLine();
}
if (line == null) {
x = -1;
} else {
System.out.println(line);
x++;
}
// Always close files.
bufferedReader.close();
} catch (FileNotFoundException ex) {
System.out.println(
"Unable to open file '"
+ fileName + "'");
} catch (IOException ex) {
System.out.println(
"Error reading file '"
+ fileName + "'");
// Or we could just do this:
// ex.printStackTrace();
}
}
yield();
}
else if (Thread.currentThread().getName().contains("writer")) {
if (x != -1 && line != null&&j==1)
{
j=0;
String fileName = "d:/salfar1.txt";
try {
// Assume default encoding.
FileWriter fileWriter =
new FileWriter(fileName, true);
// Always wrap FileWriter in BufferedWriter.
BufferedWriter bufferedWriter =
new BufferedWriter(fileWriter);
// Note that write() does not automatically
// append a newline character.
bufferedWriter.write(line);
bufferedWriter.newLine();
System.out.println("y");
// Always close files.
bufferedWriter.close();
} catch (IOException ex) {
System.out.println(
"Error writing to file '"
+ fileName + "'");
// Or we could just do this:
// ex.printStackTrace();
}
}
Thread.yield();
}
else{}
}
}
public static void main(String[] args) {
thread1 p = new thread1("Reader");
thread1 c = new thread1("writer");
p.start();
c.start();
}
}
Thanks
答案 0 :(得分:11)
您无法控制线程执行的顺序。但是,要通过单独的线程执行读写操作,您应该使用具有以下属性的BlockingQueue:
一个队列,它还支持在检索元素时等待队列变为非空的操作,并在存储元素时等待队列中的空间可用。
ReaderThread将从输入文件中读取。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
public class ReaderThread implements Runnable{
protected BlockingQueue<String> blockingQueue = null;
public ReaderThread(BlockingQueue<String> blockingQueue){
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(new File("./inputFile.txt")));
String buffer =null;
while((buffer=br.readLine())!=null){
blockingQueue.put(buffer);
}
blockingQueue.put("EOF"); //When end of file has been reached
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch(InterruptedException e){
}finally{
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
WriterThread将写入输出文件。
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.concurrent.BlockingQueue;
public class WriterThread implements Runnable{
protected BlockingQueue<String> blockingQueue = null;
public WriterThread(BlockingQueue<String> blockingQueue){
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
PrintWriter writer = null;
try {
writer = new PrintWriter(new File("outputFile.txt"));
while(true){
String buffer = blockingQueue.take();
//Check whether end of file has been reached
if(buffer.equals("EOF")){
break;
}
writer.println(buffer);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(InterruptedException e){
}finally{
writer.close();
}
}
}
从Launcher类开始你的多线程读写。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Launcher {
public static void main(String[] args) {
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1024);
ReaderThread reader = new ReaderThread(queue);
WriterThread writer = new WriterThread(queue);
new Thread(reader).start();
new Thread(writer).start();
}
}
答案 1 :(得分:-1)
这是我的解决方案。我的想法是使用我们的线程将读取和写入的实际文件名。我们需要确保只有一个问题,即没有两个线程试图在同一个文件上运行。解决方案是在run方法中简单地使用同步代码块。
我们必须记住,字符串在Java中是不可变的。请考虑以下事项:
String s1 = "test.txt";
String s2 = "test.txt";
现在,我们必须问自己,jvm如何重用不可变的“test.txt”。在这种情况下,s1和&amp; s2 String对象指向相同的“test.txt”。
理解这个概念对我们来说也是有用的:
public class Client {
public static void main( String args [] ) {
String filename = "test.txt";
String filename2 = "test.txt";
Reader reader = new Reader( filename ) ;
Writer writer = new Writer( filename2 ) ;
while(true) {
reader.run();
writer.run();
}
}
}
public class Writer implements Runnable {
public String filename;
public Writer( String filename ) {
this.filename = filename;
}
@Override
public void run() {
synchronized( this.filename ) {
System.out.println( "writing to a file:" + this.filename );
}
}
}
public class Reader implements Runnable {
public String filename;
public Reader( String filename ) {
this.filename = filename;
}
@Override
public void run() {
synchronized( this.filename ) {
System.out.println( "reading a file:" + this.filename );
}
}
}