繁体   English   中英

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

[英]Threads occasionally blocking while writing to the same file

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

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

citireInteger是对另一个读取Integer文件的线程的引用。

这是分别处理从String和Integer文件读取的类中的相关代码:

@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();
    }
}

读取Integer文件的线程:

    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();
    }
}

发生的情况是,一个线程正在另一线程上调用notifyAll ,然后在与自己的编写器同步以调用wait之前被切换出去。 另一个线程进行写操作,在其写程序上进行同步,然后调用wait 然后,第一个线程再次进入,在其编写器上同步,并调用wait 有你的僵局。

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

当您通知另一个线程时,另一个线程将仅在其他线程正在等待时看到它。 如果另一个线程在该同步块之外,则在收到通知进入该同步块,然后它将等待一个通知,该通知不会发生,或者宁可发生,也不会在它开始等待之前发生。 很难真正确定此练习的目标是什么,但是我猜想这是两个线程轮流执行写操作的原因。 好的,那么,如何使synced(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();
       }
    }

暂无
暂无

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

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