我正在嘗試最近學到的多線程的一些概念,但無法運行它。Java多線程代碼給出錯誤 - IllegalMonitorException
它給IlleagalMonitorStateException但沒有找出錯誤發生的原因。
所以關於代碼2的線程參考名稱填充&編寫者都共享arraylist填充正在填充arraylist與整數(但將填充到30),並在每個數字添加填充和寫入線程後讀取arraylist獲取該項目將其寫入文件從arraylist中刪除它。爲了更好的理解評論被添加到代碼中。
package com.utsav.pratice;
import java.io.*;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
//shared arraylist-synchronized
ArrayList<Integer> integerArrayList = new ArrayList<>();
//writter will write to this file numbers added to arraylist by filler and than will remove it from arraylist
FileOutputStream file = new FileOutputStream("Numbers.txt");
//filler will mark it true after completing all numbers
final boolean[] numbersCompleted = {false};
Thread filler=new Thread(new Runnable(){
@Override
public void run(){
//1-30 numbers one by one will be written to Arraylist
for (int i = 1; i < 31; i++) {
synchronized (integerArrayList) {
//if arraylist is not empty that means writter not performed on arraylist hence invoking wait to release lock so writter could perform
while(!integerArrayList.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//so arraylist is empty now lets fill it,notify that releasing lock and than put thread to sleep
integerArrayList.add(i);
System.out.println("Number added");
if(i==30){
numbersCompleted[0] =true;}
notifyAll();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Numbers adding completed");
}
});
Thread writter=new Thread(new Runnable(){
@Override
public void run(){
//if numbers are completed than nothing to write come out of loop
while(!numbersCompleted[0]) {
synchronized (integerArrayList) {
//if arraylist is empty than its time for filler to work hence putting thread to wait so lock could be released for filler
while (integerArrayList.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//so arraylist is not empty now lets write it & than remove it from arraylist,notify that releasing lock and than put thread to sleep
try (DataOutputStream fileWritter = new DataOutputStream(new BufferedOutputStream(file));) {
fileWritter.writeInt(integerArrayList.get(0));
System.out.println("Random number written");
} catch (IOException e) {
e.printStackTrace();
}
integerArrayList.remove(0);
notifyAll();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("File written completely");
}
});
//starting both threads-2cases filler takes the key-ok(will fill & wait) or filler takes the key(will wait since will be empty)
writter.start();
filler.start();
[閱讀'notifyAll()'](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notifyAll())的Javadoc:「[引發] IllegalMonitorStateException - 如果當前線程不是此對象監視器的所有者。「你正在調用'notifyAll()'而不同步'this'。 –
在多線程中學習的最佳概念是:不要嘗試在Object上使用低級多線程方法;改爲使用來自'java.util.concurrent'的高級構造。他們將對Java中的多線程進行更加溫和和有用的介紹。 –
請注意''final boolean [] numbersCompleted = {false};'不是線程之間完成信號完成的可靠方法。不能保證更新'numbersCompleted [0]'在其他線程中可見。你應該使用'AtomicBoolean'。 –