Java多线程代码提供错误 - IllegalMonitorException

时间:2017-03-03 08:20:18

标签: java multithreading illegalmonitorstateexcep

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

它提供了IlleagalMonitorStateException,但没有找出错误原因。

所以关于代码2线程 - 引用名称 - 填充&am​​p; writter都在共享一个arraylist-filler正在用整数填充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();

1 个答案:

答案 0 :(得分:1)

下面:

synchronized (integerArrayList) 

您正在列表上进行同步。

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

抛出此异常表示某个线程试图在对象的监视器上等待,或者在没有指定监视器的情况下通知在对象监视器上等待的其他线程。

因此,当您将其更改为

时,事情应该有效
integerArrayList.wait()
例如

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

提示:不要做像

这样的事情
final ArrayList<Integer> integerArrayList = new ArrayList<>();

只是去

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

只需使用具体的impl类类型作为变量的类型;而且也不是它的名字的一部分!