Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 线程在写入同一文件时偶尔会阻塞_Java_Multithreading - Fatal编程技术网

Java 线程在写入同一文件时偶尔会阻塞

Java 线程在写入同一文件时偶尔会阻塞,java,multithreading,Java,Multithreading,我试图使用两个单独的线程读取两个文本文件(具有相同的行数,即10000行),一个文件包含字符串,另一个包含整数。之后,我想从结果集中的相应位置写入另一个文本文件(字符串、整数)值,每个值位于不同的行上。出于这些目的,我使用了两个类来实现Runnable接口 我面临的问题是,每次我运行程序时,都有可能有一个线程正在阻止执行,我不明白为什么我在同步的块中使用wait()和notify()。更具体地说,有时程序会成功运行以完成执行,而在大多数情况下,它会在不同的阶段停止(例如,在10000行中写入约3

我试图使用两个单独的线程读取两个文本文件(具有相同的行数,即10000行),一个文件包含字符串,另一个包含整数。之后,我想从结果集中的相应位置写入另一个文本文件(字符串、整数)值,每个值位于不同的行上。出于这些目的,我使用了两个类来实现Runnable接口

我面临的问题是,每次我运行程序时,都有可能有一个线程正在阻止执行,我不明白为什么我在
同步的
块中使用wait()和notify()。更具体地说,有时程序会成功运行以完成执行,而在大多数情况下,它会在不同的阶段停止(例如,在10000行中写入约3000行,甚至约500行)

citireInteger是对读取整数文件的另一个线程的引用

下面是分别处理从字符串和整数文件读取的类的相关代码:

@Override
public void run(){

    ........
    try {
        pw = new PrintWriter(new BufferedWriter(new FileWriter("rezultat.txt", true)));

        for(int i = 0; i < strings.size(); i++){

            synchronized(this){
                pw.write(strings.get(i));
            }

            synchronized(citireInteger){
                citireInteger.notifyAll();
            }

            try{
                synchronized(this){
                    wait();
                }
            } catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    } catch(FileNotFoundException e){
        e.printStackTrace();
    } catch(IOException e){
        e.printStackTrace();
    } finally{
        pw.close();
    }

    synchronized(citireInteger){
        citireInteger.notify();
    }
}
@覆盖
公开募捐{
........
试一试{
pw=新的PrintWriter(新的BufferedWriter(新的FileWriter(“rezultat.txt”,true));
对于(int i=0;i
读取整数文件的线程:

    public void run(){

    ...........

    try{
        pw = new PrintWriter(new BufferedWriter(new FileWriter("rezultat.txt", true)));

        for(int i = 0; i < ints.size(); i++){

            synchronized(this){
                pw.write(ints.get(i) + '\n');
                System.out.println(ints.get(i));
            }
            synchronized(citireString){
                citireString.notifyAll();
            }

            try{
                synchronized(this){
                    wait();
                }
            } catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    } catch(FileNotFoundException e){
        e.printStackTrace();
    } catch(IOException e){
        e.printStackTrace();
    } finally{
        pw.close();
    }

    synchronized(citireString){
        citireString.notify();
    }
}
public void run(){
...........
试一试{
pw=新的PrintWriter(新的BufferedWriter(新的FileWriter(“rezultat.txt”,true));
对于(int i=0;i
发生的情况是,一个线程正在调用另一个线程上的
notifyAll
,然后在其自己的写入程序上同步以调用
wait
之前被切换出去。另一个线程执行写入操作,在其写入程序上进行同步,并调用
wait
。然后第一个线程再次被切换,在其写入程序上同步,并调用
wait
。这是你的僵局


最好是让两个线程在同一个对象上同步以进行写入。最好是以线程安全的方式将数据存储在内存中,并在两个线程的读取完成后从一个线程写入。

当您通知另一个线程时,另一个线程只会在其他线程等待时看到。如果另一个线程在该同步块之外,并在收到通知后进入该同步块,那么它将等待不会发生的通知,或者更确切地说,在开始等待之前发生的通知。 很难真正确定这个练习的目的是什么,但我猜它是关于两个线程轮流进行写操作。好的,那么,让synchronized(citireInt/String)块包含整个代码怎么样!这样,试图获取锁的另一个线程只会在另一个线程等待时获取该锁。我认为这将保证没有阻塞,结果将是两个线程轮流执行,一个接一个

编辑:不完全像我描述的那样,但关键点是在哪里同步

   public void run()
   {
       ...........

       try
       {
           pw = new PrintWriter(new BufferedWriter(new FileWriter("rezultat.txt", true)));

           synchronized(this)
           {
               for(int i = 0; i < ints.size(); i++)
               {
                   pw.write(ints.get(i) + '\n');
                   System.out.println(ints.get(i));

                   synchronized (citireString)
                   {
                       citireString.notifyAll();
                   }

                   try
                   {
                       wait();
                   }
                   catch (InterruptedException e)
                   {
                       e.printStackTrace();
                   }
               }
           }
       }
       catch (Throwable e)
       {
           e.printStackTrace();
       }
       finally
       {
           pw.close();
       }
    }
public void run()
{
...........
尝试
{
pw=新的PrintWriter(新的BufferedWriter(新的FileWriter(“rezultat.txt”,true));
已同步(此)
{
对于(int i=0;i
老实说,用多个线程写入同一个文件。我怀疑这会大大提高绩效。是的,我知道这一点,但这是学术目的所必需的。什么是citireInteger?我编辑了这个问题以回答你的问题。我对wait()有一个观察结果;在第三个同步块->中,它是否应该让字符串读取线程等待读取整数?但我相信它是在第二次同步后调用的,而不是在第一次同步结束后调用的。。。我只是想澄清一下。在for语句之前,启动synchronized(citireString)块。整个for循环本身进入整个synchronized块。另一个线程也是如此。等待是不可能的