【问题标题】:read and write files in java using separate threads使用单独的线程在java中读取和写入文件
【发布时间】:2023-04-01 13:42:01
【问题描述】:

我创建了两个线程并修改了 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

【问题讨论】:

  • 因为不幸的是,这就是 Threads 所做的!!!
  • 向我们展示您的相关代码。在一个线程中读取一行然后在另一个线程中写入它也是一个坏主意,因为这使得它本质上是连续的。相反,如果您要读入缓冲区,则可以让线程以更并行的方式工作。
  • 发布你的代码 [到目前为止你做了什么]
  • 你被困在producer and consumer problem 使用等待和通知逻辑来摆脱它并发布一些代码以获得帮助
  • 我已附上代码。我是 java 新手,因为它只用于类分配,所以代码可能不是最优化的。

标签: java multithreading


【解决方案1】:

您无法控制线程执行的顺序。但是,要通过单独的线程执行读写操作,您应该使用具有以下属性的 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();

  }

 }

【讨论】:

    【解决方案2】:

    这是我的解决方案。我的想法是使用我们的线程将读取和写入的实际文件名。我们只需要确保一个问题,即没有两个线程试图对同一个文件进行操作。解决方案是在 run 方法中简单地使用同步代码块。

    我们必须记住,字符串在 Java 中是不可变的。考虑以下几点:

    String s1 = "test.txt";
    String s2 = "test.txt";
    

    现在,我们必须问自己 jvm 如何重用不可变的“test.txt”。在这种情况下,s1 和 s2 字符串对象都指向同一个“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 );
        } 
    
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多