我试图使用两个单独的线程读取两个文本文件(具有相同的行数,即10000),一个文件包含字符串,另一个文件包含整数。之后我想在结果集中的相应位置写入另一个文本文件(String,Integer)值,每个值都在不同的行上。出于这些目的,我使用了两个实现Runnable接口的类。
我面临的问题是,每次运行程序时,其中一个线程都有可能阻止执行,我不明白为什么考虑我正在使用wait()和notify( )在synchronized
块中。更具体地说,有时程序运行成功完成执行,而在大多数情况下它会在各个阶段停止(例如,写入10000行,甚至约500行)。
citireInteger是对正在读取整数文件的其他线程的引用。
以下是分别处理从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();
}
}
读取整数文件的线程:
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();
}
}
答案 0 :(得分:0)
发生的事情是,一个线程在另一个线程上调用notifyAll
,然后在同步其自己的编写器之前切换到调用wait
。另一个线程执行写操作,在其编写器上进行同步,并调用wait
。然后第一个线程再次切换,在其编写器上同步,并调用wait
。这是你的僵局。
最好让两个线程在同一个对象上同步写入。最好的方法是以线程安全的方式将数据存储在内存中,一旦从两个线程读取完毕,就从单个线程写入。
答案 1 :(得分:0)
当您通知另一个线程时,另一个线程只会看到其他线程正在等待它。我的另一个线程在同步块之外,并且在通知之后进入同步块,然后它将等待一个不会发生的通知,或者更确切地说,比在它开始之前发生的通知等待它。 很难真正确定这项练习的目的是什么,但我猜测这是关于两个线程轮流做写。好的,那么,如何使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();
}
}