[英]Getting IllegalMonitorStateException while using wait() in Job scheduler
[英]Getting IllegalMonitorStateException while printing arraylist using threads
我正在嘗試使用 2 個線程打印出 arraylist 的內容,我的主要目標是讓線程以同步的方式讀取 arraylist 並打印其內容。 即使我使用同步塊,我仍然收到 IllegalMonitorStateException。 我知道這是一個基本問題,但我無法讓它工作,請原諒我。
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Q1 {
public static Q1 yeni;
public static void main(String[] args) {
// TODO Auto-generated method stub
yeni = new Q1();
}
Q1() {
List<String> list = Collections.synchronizedList(new ArrayList<String>());
list.add("a1");
list.add("b1");
list.add("c1");
list.add("d1");
list.add("e1");
list.add("f1");
ExecutorService executorService = Executors.newFixedThreadPool(10);
synchronized (list) {
myThread thread1 = new myThread(list);
myThread thread2 = new myThread(list);
thread1.start();
thread2.start();
}
}
}
這是myThread class
import java.util.*;
public class myThread extends Thread {
List<String> liste;
public myThread(List<String> liste) {
this.liste = liste;
}
@Override
public void run() {
try {
synchronized (Q1.yeni) {
System.out.println("Thread number " + this.getName() + " started running.");
for (int i = 0; i < liste.size(); i++) {
System.out.println(liste.get(i));
this.wait(3000);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
IllegalMonitorStateException
的原因是您在 object ( this
) 上調用wait
而不持有該 object 的監視器。 您必須使用synchronized (this)
塊包裝此調用,或在此代碼已同步的Q1.yeni
上調用wait
。
但是,看起來使用wait
可能是錯誤的。 此方法用於等待某個條件,該條件通過調用同一 object 上的notify
或notifyAll
來發出信號。 由於此代碼中沒有明顯的條件,並且沒有使用notify
或notifyAll
,我懷疑您真正想要調用的是this.sleep(3000)
,它將線程暫停三秒鍾,然后在該持續時間過去后恢復它.
sleep
方法不需要任何監視器的所有權,也不會釋放持有的監視器的所有權,因此另一個線程將無法在當前睡眠時進入synchronized (Q1.yeni)
塊。 這意味着進入該塊的第一個線程將運行完成,遍歷整個列表,然后第二個線程有機會開始。 目前尚不完全清楚這是否是這里的意圖。
有關更多使用信息,請參閱Object.wait
和Thread.sleep
的文檔。
第二個問題是, Q1.yeni
在它必須初始化之前就被這些線程訪問了,因為線程是在Q1
構造函數中啟動的,並且語句yeni = new Q1();
僅在構造函數完成后分配yeni
。 在這種情況下,線程使用synchronized (liste)
可能會更好。
除此之外,在Q1
構造函數中使用synchronized (list)
並沒有太大的作用,因為主線程不會訪問或操作該部分中list
的內容。 唯一實際的影響是它啟動的線程在到達第一次調用liste.size()
時會阻塞,直到主線程退出synchronized (list)
(在啟動兩個線程后立即)。 這可能會稍微減慢運行的第一個線程,但不會影響程序的線程安全或正確性。
我還建議查看“如何在 Java 中處理 InterruptedException” 。 在這種情況下,我建議在異常處理程序中恢復中斷狀態。
放在一起,這里是這個代碼的修改示例(包括其他小的更改,以刪除未使用的代碼和樣板注釋,改進格式,並確保與 Java 命名約定的一致性):
Q1.java
:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Q1 {
private static Q1 yeni;
public static void main(String[] args) {
yeni = new Q1();
}
Q1() {
List<String> list = Collections.synchronizedList(new ArrayList<>());
list.add("a1");
list.add("b1");
list.add("c1");
list.add("d1");
list.add("e1");
list.add("f1");
MyThread thread1 = new MyThread(list);
MyThread thread2 = new MyThread(list);
thread1.start();
thread2.start();
}
}
MyThread.java
:
import java.util.*;
public class MyThread extends Thread {
private final List<String> liste;
public MyThread(List<String> liste) {
this.liste = liste;
}
@Override
public void run() {
try {
synchronized (liste) {
System.out.println("Thread number " + this.getName() + " started running.");
for (int i = 0; i < liste.size(); i++) {
System.out.println(liste.get(i));
sleep(3000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
interrupt();
}
}
}
Output:
Thread number Thread-0 started running.
a1
b1
c1
d1
e1
f1
Thread number Thread-1 started running.
a1
b1
c1
d1
e1
f1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.