併發 錯誤 java.lang.IllegalMonitorStateException: current thread not owner 分析

public class ThreadTest implements Callable<String> {

	 public  String call() throws Exception {
		// TODO Auto-generated method stub
		wait(10000);
		return "hello";
	}

}
調用代碼:

public static void main(String[] args) {
		System.out.println("開始啓動線程"+Thread.currentThread().getName());
		ExecutorService exe = Executors.newCachedThreadPool();
		ThreadTest t= new ThreadTest();
		Future<String> f = exe.submit(t);
		Future<String> f2 = exe.submit(t);
		try {
			
				t.notify();
			
			System.out.println(f.get());
			System.out.println(f2.get());
			System.out.println("主線程"+Thread.currentThread().getName());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}



在學習併發是遇到了例如如下錯誤html

java.lang.IllegalMonitorStateException: current thread not ownerjava

個人代碼例如如下:編程


經過查找資料找到緣由即解決之道。併發

《java編程思想》第四版一書中有描寫敘述到:「線程操做的wait()、notify()、notifyAll()方法僅僅能在同步控制方法或同步控制塊內調用。學習

假設在非同步控制方法或控制塊裏調用。程序能經過編譯,但運行的時候,將獲得 IllegalMonitorStateException 異常。並伴隨着一些含糊信息,比方 ‘當前線程不是擁有者’。spa

事實上異常的含義是 調用wait()、notify()、notifyAll()的任務在調用這些方法前必須 ‘擁有’(獲取)對象的鎖。線程

code


JAVA JDK API文檔中也有描寫敘述例如如下:htm

wait()、notify()、notifyAll()法僅僅應由做爲此對象監視器的所有者的線程來調用。對象

經過下面三種方法之中的一個,線程可以成爲此對象監視器的所有者:

  • 經過運行此對象的同步 (Sychronized) 實例方法。
  • 經過運行在此對象上進行同步的 synchronized 語句的正文。

  • 對於 Class 類型的對象,可以經過運行該類的同步靜態方法。

依據以上分析,個人代碼改動例如如下:

一、call方法前添加synchronizedkeyword,這樣調用wait()方法就不會出錯了。

二、在t.notify()方法調用時使用同步上下文。改成例如如下:

synchronized (t) {
t.notify();
}

再次運行就正常了。

相關文章
相關標籤/搜索