简体   繁体   English

多线程的Java问题

[英]Java Problems of Multithreading

I have problem with synchronized reading of my file. 我有同步读取我的文件的问题。 The case is simple: to handle data in the file. 案例很简单:处理文件中的数据。 My problem is synchronization. 我的问题是同步。 I try to make it on object reader of class BufferedReader, but I have two problems. 我尝试在类BufferedReader的对象读取器上创建它,但我有两个问题。 If I initialise reader in "try with resourses" of my method read() I will get to different objects of BufReader for the same object when I use it in different theads. 如果我在我的方法read()的“尝试使用资源”中初始化读者,当我在不同的theads中使用它时,我会得到同一个对象的BufReader的不同对象。 The second one I initialise it in class and get the same object for threads, but a great problem with exeptions and unpredictable behavior. 第二个我在类中初始化它并为线程获取相同的对象,但是exeptions和不可预测的行为是一个很大的问题。 I will write code for the second situation. 我会为第二种情况编写代码。 Can you advice me how to solve. 你能建议我如何解决。 I am studying now, that's why I want advices. 我正在学习,这就是我想要的建议。

class FileReaderClass {
    private File file = new File("src\\exer1\\Transfers.txt");
    private BufferedReader reader = null;
    private FileReader fr = null;

    StringBuilder sb = new StringBuilder();

    void read() throws IOException {
        try {
            fr = new FileReader(file);
            reader = new BufferedReader(fr);
            String buftext;
                while ((buftext = reader.readLine()) != null){
                    synchronized (reader) {
                        System.out.println(Thread.currentThread().getName());//for testing
                        sb.append(buftext).append("\n");
                        //System.out.println(buftext);
                    }
                }
            }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if (reader != null)
                reader.close();
            if (fr != null)
                fr.close();
        }
    }
}

class Reader1 implements Runnable {

    private FileReaderClass frc;

    public Reader1(FileReaderClass frc) {
        this.frc = frc;
    }

    @Override
    public void run() {
        try {
            frc.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class Ex1 {
    public static void main(String[] args) throws InterruptedException {
        FileReaderClass frc = new  FileReaderClass();
        Thread t1 = new Thread(new Reader1(frc));
        Thread t2 = new Thread(new Reader2(frc));

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("---------------------");
        System.out.println(frc.sb);

    }
}

You are sharing the same FileReaderClass instance (that is frc ) in two threads. 您在两个线程中共享相同的FileReaderClass实例(即frc )。 Your FileReaderClass is not thread safe, that causes the problems. 您的FileReaderClass不是线程安全的,这会导致问题。 There are two alternatives here: 这里有两种选择:

  • Create another instance of FileReaderClass , so that both threads will use different instances. 创建另一个FileReaderClass实例,以便两个线程都使用不同的实例。
  • Mark the method read as snychronized . read的方法标记为snychronized

You are synchronizing on the wrong level. 您正在以错误的级别进行同步。 Your sync guard is useless, as there are actually two reader s. 你的同步保护是没用的,因为实际上有两个reader That's because each time read is called, a reader will be created, which will be a separate instance. 那是因为每次调用read ,都会创建一个reader ,这将是一个单独的实例。 We can't even know for sure, which reader instance was the subject of syncing. 我们甚至无法确定哪个reader实例是同步的主题。

If you want to parallelize reading of your file you should use the same reader but use proper synchronization for each read by any thread, so that it stays consistent, the easiest way is to make the whole read method synchronized and instantiate your readers in your class constructor. 如果要并行读取文件,则应使用相同的读取器,但对任何线程的每次读取使用正确的同步,以使其保持一致,最简单的方法是使整个读取方法同步并在类中实例化读者构造函数。

As you may want to read and write to your string builder in the correct order, the thread that reads a line must only release the lock after it writes to StringBuilder, making your whole method to be pretty much guarded by a lock. 由于您可能希望以正确的顺序读取和写入字符串构建器,因此读取行的线程必须仅在写入StringBuilder后释放锁定,从而使整个方法几乎受到锁定的保护。 It will work but you won't gain any performance, and for small files it may cause too much overhead, but as an exercise it may suffice. 它可以工作,但你不会获得任何性能,对于小文件,它可能会导致太多的开销,但作为练习,它可能就足够了。

Your code as it is has the following problems 您的代码存在以下问题

  1. You are always creating new readers, thus every thread calling this method will start from the beginning. 您总是在创建新的读者,因此调用此方法的每个线程都将从头开始。
  2. As previously stated by another answear you are synchronizing at the wrong level, any thread may read and the thread scheduler can suspend it right after, causing your writes to StringBuilder object to be out of order (i think it is not intended). 正如前面提到的另一个answear,你正在错误的级别进行同步,任何线程都可以读取,线程调度程序可以在之后立即挂起它,导致你对StringBuilder对象的写入失序(我认为这不是故意的)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM