使用线程打印 arraylist 时获取 IllegalMonitorStateException
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();
}
}
}
这是我的线程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
的原因是您在对象 (this
) 上调用 wait
而没有持有该对象的监视器。您必须用 synchronized (this)
块包装此调用,或在 Q1.yeni
上调用 wait
,此代码已同步。
但是,wait
的使用似乎有误。此方法用于等待条件,该条件通过调用同一对象上的 notify
或 notifyAll
来发出信号。由于此代码中没有明显的条件,也没有使用 notify
或 notifyAll
,我怀疑您真正想要调用的是 this.sleep(3000)
,它会暂停线程三秒钟,然后在该持续时间结束后恢复它。
sleep
方法不需要任何监视器的所有权,也不会释放持有的监视器的所有权,因此另一个线程将无法进入 synchronized (Q1.yeni)
块,而另一个线程正在休眠.这意味着进入该块的第一个线程将 运行 完成,在第二个线程有机会开始之前迭代整个列表。尚不完全清楚这是否是此处的意图。
有关更多使用信息,请参阅 Object.wait
and Thread.sleep
的文档。
第二个问题是 Q1.yeni
在必须初始化之前被这些线程访问,因为线程是在 Q1
构造函数中启动的,语句 yeni = new Q1();
只分配yeni
构造函数完成后。在这种情况下,线程使用 synchronized (liste)
可能会更好。
除此之外,在 Q1
构造函数中包含 synchronized (list)
并没有完成多少,因为主线程不访问或操作该部分中 list
的内容。唯一的实际影响是,它启动的线程在到达对 liste.size()
的第一次调用时会阻塞,直到主线程退出 synchronized (list)
(在启动两个线程后立即)。这可能会稍微减慢运行的第一个线程,但对线程安全或程序的正确性没有影响。
我还建议查看 "How to Handle InterruptedException in Java"。在这种情况下,我建议在异常处理程序中恢复中断状态。
总而言之,这是此代码的修订示例(包括删除未使用的代码和样板注释、改进格式并确保与 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();
}
}
}
输出:
Thread number Thread-0 started running.
a1
b1
c1
d1
e1
f1
Thread number Thread-1 started running.
a1
b1
c1
d1
e1
f1
我正在尝试使用 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();
}
}
}
这是我的线程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
的原因是您在对象 (this
) 上调用 wait
而没有持有该对象的监视器。您必须用 synchronized (this)
块包装此调用,或在 Q1.yeni
上调用 wait
,此代码已同步。
但是,wait
的使用似乎有误。此方法用于等待条件,该条件通过调用同一对象上的 notify
或 notifyAll
来发出信号。由于此代码中没有明显的条件,也没有使用 notify
或 notifyAll
,我怀疑您真正想要调用的是 this.sleep(3000)
,它会暂停线程三秒钟,然后在该持续时间结束后恢复它。
sleep
方法不需要任何监视器的所有权,也不会释放持有的监视器的所有权,因此另一个线程将无法进入 synchronized (Q1.yeni)
块,而另一个线程正在休眠.这意味着进入该块的第一个线程将 运行 完成,在第二个线程有机会开始之前迭代整个列表。尚不完全清楚这是否是此处的意图。
有关更多使用信息,请参阅 Object.wait
and Thread.sleep
的文档。
第二个问题是 Q1.yeni
在必须初始化之前被这些线程访问,因为线程是在 Q1
构造函数中启动的,语句 yeni = new Q1();
只分配yeni
构造函数完成后。在这种情况下,线程使用 synchronized (liste)
可能会更好。
除此之外,在 Q1
构造函数中包含 synchronized (list)
并没有完成多少,因为主线程不访问或操作该部分中 list
的内容。唯一的实际影响是,它启动的线程在到达对 liste.size()
的第一次调用时会阻塞,直到主线程退出 synchronized (list)
(在启动两个线程后立即)。这可能会稍微减慢运行的第一个线程,但对线程安全或程序的正确性没有影响。
我还建议查看 "How to Handle InterruptedException in Java"。在这种情况下,我建议在异常处理程序中恢复中断状态。
总而言之,这是此代码的修订示例(包括删除未使用的代码和样板注释、改进格式并确保与 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();
}
}
}
输出:
Thread number Thread-0 started running.
a1
b1
c1
d1
e1
f1
Thread number Thread-1 started running.
a1
b1
c1
d1
e1
f1