ওয়েল () কলটিতে অবৈধমনিটর স্টেটএক্সসেপশন


162

আমি আমার প্রোগ্রামের জন্য জাভাতে মাল্টি-থ্রেডিং ব্যবহার করছি। আমি সফলভাবে থ্রেড চালিয়েছি তবে যখন আমি ব্যবহার করছি তখন Thread.wait()এটি নিক্ষেপ করছে java.lang.IllegalMonitorStateException। থ্রেডটি অবহিত না হওয়া পর্যন্ত আমি কীভাবে অপেক্ষা করতে পারি?


2
থ্রেড.ওয়েট () এর অস্তিত্ব নেই, এটি এটি হতে পারে waউইট ()
প্রেমরাজ

উত্তর:


175

কাজ synchronizedকরার জন্য Object.wait()আপনাকে একটি ব্লকে থাকা দরকার ।

এছাড়াও, আমি পুরানো স্কুল থ্রেডিং প্যাকেজগুলির পরিবর্তে একযোগে প্যাকেজগুলি দেখার পরামর্শ দিই। এগুলি কাজ করার পক্ষে সুরক্ষিত এবং সহজ উপায় ।

শুভ কোডিং।

সম্পাদনা

আমি ধরে নিয়েছি যে আপনি Object.wait()আপত্তি হিসাবে বোঝাচ্ছেন যা আপনি যখন বস্তুর লকটি ধরে না রেখে অ্যাক্সেস অর্জন করার চেষ্টা করেন তখনই ঘটে থাকে।


1
ভালো বল ধরা. আমি ধরে নিয়েছি তার অর্থ অবজেক্ট.ওয়েট () এবং একটি থ্রেড থেকে ডেকেছে
পুনরুদ্ধার করে

2
আপনি যে অবজেক্টটির অপেক্ষায় রয়েছেন তার একটি সিঙ্ক্রোনাইজড ব্লক। এই উত্তরটি কিছুটা আরও পরিষ্কার করার জন্য সম্পাদনা করার যত্ন আছে? ধন্যবাদ।
ধূসর

55

waitসংজ্ঞায়িত করা হয় Object, এবং না Thread। মনিটরটি Threadকিছুটা অনাকাঙ্ক্ষিত।

যদিও সমস্ত জাভা অবজেক্টের মনিটর রয়েছে, সাধারণত একটি ডেডিকেটেড লক রাখা ভাল:

private final Object lock = new Object();

নামযুক্ত ক্লাসটি ব্যবহার করে আপনি একটি স্বল্প মেমোরি ব্যয়ে (প্রায় 2K প্রক্রিয়ায়) ডায়াগনস্টিকগুলি পড়তে কিছুটা সহজ পেতে পারেন:

private static final class Lock { }
private final Object lock = new Lock();

জন্য waitবা notify/ notifyAllএকটি বস্তু তোমাদের সঙ্গে লক অধিষ্ঠিত করা প্রয়োজন synchronizedবিবৃতি। এছাড়াও, whileজাগ্রত শর্তটি পরীক্ষা করার জন্য আপনার একটি লুপের প্রয়োজন হবে (কেন তা বোঝানোর জন্য থ্রেডিংয়ে একটি ভাল পাঠ্য সন্ধান করুন)।

synchronized (lock) {
    while (!isWakeupNeeded()) {
        lock.wait();
    }
}

অবহিত করতে:

synchronized (lock) {
    makeWakeupNeeded();
    lock.notifyAll();
}

মাল্টিথ্রেডিংয়ের সময় জাভা ভাষা এবং java.util.concurrent.locksলকগুলি (এবং java.util.concurrent.atomic) উভয়ই বোঝা ভাল । java.util.concurrentআপনি যখনই পারেন তথ্যের স্ট্রাকচার ব্যবহার করুন।


5
আমি কখনই বুঝতে পারি না এটি কীভাবে কাজ করে, প্রদত্ত অপেক্ষা ও বিজ্ঞপ্তি দুটি একই বস্তুর (লক) সিঙ্ক্রোনাইজড ব্লকে রয়েছে। যেহেতু অপেক্ষার থ্রেডটি ব্লকটিতে রয়েছে, এটি কি "সিঙ্ক্রোনাইজড (লক)" লাইনে নোটিফাই থ্রেড ব্লক তৈরি করে না?
ব্রেন্ট 212

6
@ ব্রেন্ট 212 ছাড়া অন্য যে কোনও পদ্ধতির জন্য waitহ্যাঁ আপনি কখনই পাবেন না notify। তবে, এপিআই ডক্সে Object.wait"থ্রেডটি এই মনিটরের মালিকানা প্রকাশ করে"। waitএর মধ্যে এটির মতো যদি এটি এনকোলেজিং synchronizedব্লকের বাইরে থাকে (একই বস্তুর জন্য একই বস্তুর একাধিক synchronizedব্লক হতে পারে )।
টম হাটিন -

24

আমি জানি এই থ্রেডটি প্রায় 2 বছর পুরানো তবে এখনও বন্ধ করতে হবে যেহেতু আমি একই প্রশ্নটি নিয়ে এই প্রশ্ন / একটি অধিবেশনে এসেছি ...

দয়া করে অবৈধমনিটর ধারণাটির এই সংজ্ঞাটি বারবার পড়ুন ...

IllegalMonitorExceptionটি বোঝানো হয়েছে যে কোনও থ্রেড কোনও বস্তুর মনিটরের জন্য অপেক্ষা করার চেষ্টা করেছে বা নির্দিষ্ট মনিটরের মালিক না হয়ে কোনও থ্রেডকে অবজেক্টের মনিটরে অপেক্ষা করার চেষ্টা করেছে।

এই লাইনটি বারবার বলে, 2 অবৈধ পরিস্থিতিগুলির মধ্যে একটি যখন ঘটে তখন অবৈধমনিটরপত্তিটি আসে ....

1> নির্দিষ্ট মনিটরের মালিক না করে কোনও অবজেক্টের মনিটরে অপেক্ষা করুন।

2> নির্দিষ্ট মনিটরের মালিক না হয়ে কোনও থ্রেড অবজেক্টের মনিটরে অপেক্ষা করুন।

কিছু তাদের উত্তর পেয়ে থাকতে পারে ... যারা সমস্ত না, তারপর দয়া করে 2 টি বিবৃতি চেক করুন ...

সিঙ্ক্রোনাইজড (অবজেক্ট)

object.wait ()

যদি উভয় বস্তু একই হয় ... তবে কোনও অবৈধমনিটর ধারণাটি আসতে পারে না।

এখন আবার IllegalMonitorException সংজ্ঞাটি পড়ুন এবং আপনি এটি আবার ভুলে যাবেন না ...


আসলে, যে কাজ করে না। আমি চেষ্টা করেছি। আমি একটি রান্নেবল তৈরি করি, এটিতে লক করে থাকি (সিঙ্ক্রোনাইজড ব্লক ব্যবহার করে) এবং সেই ব্লকের ভিতরে আমি ইউআই থ্রেড (অ্যান্ড্রয়েড) এ রান্নেবল চালিত করি এবং তারপরে আমি আমাররন্যেবল.ওয়েট () করি এবং এখনও আমি ব্যতিক্রম পাই।
টেড

এক্সেলেনেট ব্যাখ্যা !! আমি অবজেক্টটি নির্দিষ্ট না করে অপেক্ষা করছিলাম (সুতরাং) এটি উদাহরণটি নিয়েছে এবং অন্য কোনও বস্তুর সাথে সিঙ্ক্রোনিকেশন করছে। এখন আমি অন্যান্যঅজেক্ট.ওয়েট () ব্যবহার করছি এবং এটি কার্যকর!
ফার্সকা

6

আপনার মন্তব্যের ভিত্তিতে মনে হচ্ছে আপনি এরকম কিছু করছেন:

Thread thread = new Thread(new Runnable(){
    public void run() { // do stuff }});

thread.start();
...
thread.wait();

তিনটি সমস্যা আছে।

  1. অন্যরা যেমন বলেছে, obj.wait()কেবলমাত্র তখনই বলা যেতে পারে যদি বর্তমান থ্রেডটির জন্য আদিম লক / মিটেক্স ধারণ করে obj। যদি বর্তমান থ্রেডটি লকটি ধরে না রাখে তবে আপনি যে ব্যতিক্রমটি দেখছেন তা পেয়ে যান।

  2. thread.wait()কল কি আপনি এটা করবেন আশা হবে বলে মনে হচ্ছে করি না। বিশেষত, মনোনীত থ্রেডটি অপেক্ষা করতে thread.wait() দেয় না । বরং এটি বর্তমান থ্রেডের জন্য অন্য কোনও থ্রেড কল thread.notify()বা অপেক্ষা করে অপেক্ষা করে thread.notifyAll()

    Threadউদাহরণস্বরূপ এটি না চাইলে বিরতি দেওয়ার জন্য কোনও নিরাপদ উপায় নেই। (জাভা এটির নিকটতম নিকটতম Thread.suspend()পদ্ধতি হ'ল অবনমিত পদ্ধতি, তবে জাভাডোকের বর্ণনা অনুসারে সেই পদ্ধতিটি সহজাতভাবে অনিরাপদ))

    আপনি যদি সদ্য শুরু Threadকরা বিরতিতে চান তবে এটি করার সর্বোত্তম উপায় হ'ল একটি CountdownLatchদৃষ্টান্ত তৈরি করা এবং থ্রেড কলটি await()ল্যাচটিতে নিজেকে থামিয়ে দেওয়া on মূল থ্রেড তখন countDown()থেমে থেমে থেমে থেমে থেমে থেমে থেমে থাকা চালিয়ে যেতে দেয়।

  3. পূর্ববর্তী পয়েন্টগুলিতে Threadঅर्थোগোনাল, লক / মুটেক্স হিসাবে কোনও বস্তু ব্যবহার করা সমস্যার কারণ হতে পারে। উদাহরণস্বরূপ, জাভাদোক Thread::joinবলেছেন:

    এই প্রয়োগটি this.waitকন্ডিশনেড কলগুলির একটি লুপ ব্যবহার করে this.isAlive। একটি থ্রেড সমাপ্তির পরে this.notifyAllপদ্ধতিটি চাওয়া হয়। এটি প্রস্তাবিত যে অ্যাপ্লিকেশন ব্যবহার করবেন wait, notifyঅথবা notifyAllউপর Threadদৃষ্টান্ত।


2

যেহেতু আপনি কোড পোস্ট করেন নি, আমরা অন্ধকারে কাজ করছি। ব্যতিক্রমের বিবরণ কী কী?

আপনি থ্রেড.ওয়েত () কে থ্রেডের মধ্যে থেকে, না বাইরে থেকে ডাকছেন?

আমি এটি জিজ্ঞাসা করছি কারণ ইলিজালমনিটরস্টেট এক্সসেপশনের জাভাদোক অনুযায়ী, এটি হ'ল:

থ্রেডটি নির্দিষ্ট মনিটরের মালিক না হয়ে কোনও বস্তুর মনিটরে অপেক্ষা করার বা অন্য থ্রেডকে অবজেক্টের মনিটরে অপেক্ষা করার চেষ্টা করেছে তা নির্দেশ করার জন্য নিক্ষিপ্ত হয়েছিল।

এই উত্তরটি স্পষ্ট করার জন্য, একটি সুতোয় অপেক্ষা করার এই কলটি একটি সিঙ্ক্রোনাইজড ব্লকের মধ্যে থেকে ডেকে আনা সত্ত্বেও, ইলিজালমনিটর স্টেটএক্সপশন নিক্ষেপ করেছে:


     private static final class Lock { }
     private final Object lock = new Lock();

    @Test
    public void testRun() {
        ThreadWorker worker = new ThreadWorker();
        System.out.println ("Starting worker");
        worker.start();
        System.out.println ("Worker started - telling it to wait");
        try {
            synchronized (lock) {
                worker.wait();
            }
        } catch (InterruptedException e1) {
            String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
            System.out.println (msg);
            e1.printStackTrace();
            System.out.flush();
        }
        System.out.println ("Worker done waiting, we're now waiting for it by joining");
        try {
            worker.join();
        } catch (InterruptedException ex) { }

    }

@ সিপারকিনস: আমি মনে করি আপনি মৃত্যুদন্ড কার্যকর করার থ্রেড এবং সেই অবজেক্টটিকে লক্ষ্য করে যা গুলিয়ে ফেলছেন wait()
রবার্ট মুন্তানু

@ রবার্ট - সম্ভবত আমি আছি, তবে আমি তা মনে করি না। যদি আপনি কোনও থ্রেড উদাহরণ শুরু করেন, এবং তারপরে অপেক্ষা করতে বলেন, আপনি একটি অবৈধমনিস্টার স্টেটএক্সসেপশন পাবেন, যা আমি বর্ণনা করার চেষ্টা করছি was
সিপারকিনস

আপনি worker.wait()লাইন সম্পর্কে কথা বলছেন ? তারপরে আপনার কর্মীর সাথে সিঙ্ক্রোনাইজ করা উচিত, লকটিতে নয়।
রবার্ট মুন্তানু

1

IllegalMonitorStateException নিয়ে কাজ করার জন্য, আপনাকে অবশ্যই যাচাইকরণ এবং সূচিতকরণের সমস্ত পদ্ধতিগুলি কলিং থ্রেডের উপযুক্ত মনিটরের মালিক হওয়ার সময় যাচাই করা উচিত । সর্বাধিক সহজ সমাধান হ'ল এই কলগুলিকে সিঙ্ক্রোনাইজড ব্লকের মধ্যে সংযুক্ত করা। সিঙ্ক্রোনাইজেশন অবজেক্টটি সিঙ্ক্রোনাইজড স্টেটমেন্টে ডাকা হবে। তার মনিটরটি অবশ্যই গ্রহণ করা উচিত।

মনিটরের ধারণাটি বোঝার জন্য এখানে সাধারণ উদাহরণ

public class SimpleMonitorState {

    public static void main(String args[]) throws InterruptedException {

        SimpleMonitorState t = new SimpleMonitorState();
        SimpleRunnable m = new SimpleRunnable(t);
        Thread t1 = new Thread(m);
        t1.start();
        t.call();

    }

    public void call() throws InterruptedException {
        synchronized (this) {
            wait();
            System.out.println("Single by Threads ");
        }
    }

}

class SimpleRunnable implements Runnable {

    SimpleMonitorState t;

    SimpleRunnable(SimpleMonitorState t) {
        this.t = t;
    }

    @Override
    public void run() {

        try {
            // Sleep
            Thread.sleep(10000);
            synchronized (this.t) {
                this.t.notify();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

0

থ্রেড.ওয়েট () কল থ্রেডক্লাস অবজেক্টে সিঙ্ক্রোনাইজ হওয়া কোনও কোডের মধ্যে কল্পনা করে। আপনি যা বোঝাতে চেয়েছিলেন তা আমি মনে করি না।
আপনি জিজ্ঞাসা করুন

থ্রেডটি অবহিত না হওয়া পর্যন্ত আমি কীভাবে অপেক্ষা করতে পারি?

আপনি কেবল আপনার বর্তমান থ্রেড অপেক্ষা করতে পারেন। অন্য কোনও থ্রেডকে সম্মতি জানালে কেবল আলতোভাবে অপেক্ষা করতে বলা যেতে পারে।
আপনি যদি কিছু শর্তের জন্য অপেক্ষা করতে চান তবে আপনার একটি লক অবজেক্টের দরকার - থ্রেডক্লাস অবজেক্টটি খুব খারাপ পছন্দ - এটি একটি সিঙ্গলটন আফাইক তাই এটির উপর সিঙ্ক্রোনাইজ করা (থ্রেড স্ট্যাটিক পদ্ধতি ব্যতীত) বিপজ্জনক।
সিঙ্ক্রোনাইজেশন এবং অপেক্ষার বিবরণগুলি টম হাটিন ইতিমধ্যে ব্যাখ্যা করেছেন। java.lang.IllegalMonitorStateExceptionএর অর্থ আপনি যে বস্তুর উপরে সিঙ্ক্রোনাইজ হননি তার অপেক্ষার চেষ্টা করছেন - এটি করা অবৈধ।


0

নিশ্চিত নয় যে এটি অন্য কাউকে সাহায্য করবে কিনা বা না তবে ব্যবহারকারী "টম হাটিন - ট্যাকলিন" এর উত্তরটিতে আমার সমস্যাটি সমাধান করার জন্য এটি মূল অংশ ছিল:

synchronized (lock) {
    makeWakeupNeeded();
    lock.notifyAll();
}

কেবল "লক" সিঙ্ক্রোনাইজড () এ আর্গুমেন্ট হিসাবে পাস হয়েছে এবং এটি "লক" -তেও ব্যবহৃত হয় not

একবার আমি 2 টি জায়গায় এটি তৈরি করে আমি এটি কাজ করেছিলাম


0

আমি IllegalMonitorStateException/ আলাদা class/ থ্রেড থেকে একটি থ্রেড জাগ্রত করার চেষ্টা করার সময় পেয়েছি । ইন java 8আপনি ব্যবহার করতে পারেন lockনতুন concurrency API- এর বৈশিষ্ট্য পরিবর্তে এর synchronizedফাংশন।

আমি ইতিমধ্যে asynchronousএকটিতে ওয়েবসকেট লেনদেনের জন্য বস্তুগুলি সংরক্ষণ করছিলাম WeakHashMap। আমার ক্ষেত্রে সমাধানটি ছিল উত্তরগুলির জন্য একটি lockবস্তু সংরক্ষণ করাConcurrentHashMapsynchronousনোট করুন condition.await(না .wait)

মাল্টি থ্রেডিং পরিচালনা করতে আমি Executors.newCachedThreadPool()একটি থ্রেড পুল তৈরি করতে ব্যবহার করেছি used


0

যাঁরা জাভা .0.০ বা নীচের সংস্করণটি ব্যবহার করছেন তারা কোডটি এখানে ব্যবহার করতে পারেন যা এটি ব্যবহার করে it

public class WaitTest {

    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();

    public void waitHere(long waitTime) {
        System.out.println("wait started...");
        lock.lock();
        try {
            condition.await(waitTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        lock.unlock();
        System.out.println("wait ends here...");
    }

    public static void main(String[] args) {
        //Your Code
        new WaitTest().waitHere(10);
        //Your Code
    }

}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.