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();
}
再次運行就正常了。