Java多线程代码给出错误-Illegal Monitor Exception

标签 java multithreading illegalmonitorstateexcep

我正在尝试最近学到的一些多线程概念,但无法运行它。

它给出了 IllegalMonitorStateException 但没有弄清楚错误发生的原因。

因此,关于代码2线程引用名称填充器和写入器都共享一个数组列表,填充器正在用整数填充数组列表(但最多填充30个),并且在填充器和写入器线程添加每个数字后读取数组列表获取该项目将其写入文件将其从数组列表中删除。为了更好地理解,在代码中添加了注释。

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

最佳答案

这里:

synchronized (integerArrayList) 

您正在列表上进行同步。

但是您正在等待/通知您的匿名线程对象的this!作为 javadoc 中的第一个信息说:

抛出该异常表示线程尝试在对象的监视器上等待,或通知在不拥有指定监视器的情况下在对象的监视器上等待的其他线程。

所以当你将它们更改为

时,事情应该会起作用
integerArrayList.wait()

例如(所有使用 wait/notify/...)!

并提示:不要做类似的事情

final ArrayList<Integer> integerArrayList = new ArrayList<>();

只是去

List<Integer> numbers = new ArrayList<>();

简单地使用具体的 impl 类类型作为变量的类型;而且也不作为其名称的一部分!

关于Java多线程代码给出错误-Illegal Monitor Exception,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42573841/

相关文章:

java - 如何在 Spring Boot 中从资源服务器中的 token 中提取声明

Swift OSX - 从另一个类或者线程更新 NSTextView

c++ - 如何在 C++ 中将 std::thread::id 转换为字符串?

java - Hadoop 序列文件大小

java - 非静态API的终结点是什么?

java - 如何在 Java 中将文件路径列表转换为 JSON 对象

ios - 如何在另一个线程上正确打开和关闭 NSStream

java - 两个线程等待时非法监视器状态异常

java - 带条件的 IllegalMonitorStateException