Многопоточный код Java дает ошибку-IllegalMonitorException

java multithreading illegalmonitorstateexcep

45 просмотра

1 ответ

6 Репутация автора

Я пробовал некоторые концепции многопоточности, изученные недавно, но не смог их запустить.

Это дает IlleagalMonitorStateException, но не выясняет ошибку, почему это происходит.

Так что о коде-2 thread-reference names-filler и writer оба совместно используют arraylist-filler заполняет arraylist целым числом (но будет заполнять его до 30), и после того, как каждый номер будет добавлен filler, а поток писателя прочитает 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();
Автор: utsav madaan Источник Размещён: 03.03.2017 08:20

Ответы (1)


1 плюс

109556 Репутация автора

Решение

Вот:

synchronized (integerArrayList) 

Вы синхронизируете в своем списке .

Но вы ждете / уведомите об этом ваши анонимные объекты потока! И как говорится в самой первой информации в Javadoc :

Брошенный, чтобы указать, что поток попытался ждать на мониторе объекта или уведомить другие потоки, ожидающие на мониторе объекта, не имея указанного монитора.

Так что все должно работать, когда вы меняете их на

integerArrayList.wait()

например (все использование wait / notify / ...)!

И подсказка: не делай такие вещи, как

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

просто пойти на

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

Просто не используйте конкретный тип класса impl в качестве типа вашей переменной; а также не как часть его имени!

Автор: GhostCat Размещён: 03.03.2017 08:38
Вопросы из категории :
32x32