Java Thread Programming 1.8.2 – Inter-thread Communication

來源:互聯網
上載者:User
Missed Notification A missed notification occurs when threadB tries to notify threadA, but threadA is not yet waiting for the notification. In a multithreaded environment like Java, you don’t have much control over which thread runs and for how long. This uncertainty can lead to a situation in which most of the time an application is run, threadA is waiting before threadB does the notification. But occasionally, threadB does the notification before threadA is waiting. This missed notification scenario can be quite dangerous. Missed Notification指:線程B試圖通知線程A,但線程A並沒有在等待通知。這並不是不可能出現的。在多線程環境中,我們不能控制哪個線程執行,執行多長時間,這種不確定有可能導致在一個線程等待之前就先行通知,這是一種很危險的情況。如下程式會出現這種情況: /* * Created on 2005-7-14 * * Java Thread Programming - Paul Hyde  * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 *  */package org.tju.msnrl.jonathan.thread.chapter8; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo *      blog.yesky.net/jonathanundersun *  * Enjoy Life with Sun! *  */public class MissedNotify {        private Object proceedLock;        public MissedNotify(){                proceedLock = new Object();    }        public void waitProceed() throws InterruptedException{        print("in waitProceed() - begin");                synchronized(proceedLock){            print("begin synchronized wait ...");            proceedLock.wait();            print("end synchronized wait ...");        }                print("in waitProceed() - end");    }        public void notifyProceed(){        print("in notifyProceed() - begin");                synchronized(proceedLock){            print("begin synchronized notify ...");            proceedLock.notifyAll();            print("end synchronized notify ...");        }                print("in notifyProceed() - end");    }        public static void print(String msg){        String temp = Thread.currentThread().getName();        System.out.println(temp + " - " + msg);    }     public static void main(String[] args) {        final MissedNotify mn = new MissedNotify();                Runnable runA = new Runnable(){            public void run(){                try{                    Thread.sleep(1000);//wait()後執行                    mn.waitProceed();                }catch(InterruptedException e){                    e.printStackTrace();                }            }        };                Thread threadA= new Thread(runA,"threadA");        threadA.start();                Runnable runB = new Runnable(){            public void run(){                try{                    Thread.sleep(500);//notify()先執行                    mn.notifyProceed();                }catch(InterruptedException e){                    e.printStackTrace();                }            }        };                Thread threadB = new Thread(runB,"threadB");        threadB.start();                try{            Thread.sleep(10000);        }catch(InterruptedException e){                    }                print("interrupt thread A ...");        threadA.interrupt();    }} 輸出結果:threadB - in notifyProceed() - beginthreadB - begin synchronized notify ...threadB - end synchronized notify ...threadB - in notifyProceed() - endthreadA - in waitProceed() - beginthreadA - begin synchronized wait ...main - interrupt thread A ...java.lang.InterruptedException     at java.lang.Object.wait(Native Method)     at java.lang.Object.wait(Object.java:429)     at org.tju.msnrl.jonathan.thread.chapter8.MissedNotify.waitProceed(MissedNotify.java:35)     at org.tju.msnrl.jonathan.thread.chapter8.MissedNotify$1.run(MissedNotify.java:66)     at java.lang.Thread.run(Thread.java:534)  解決方案:只需加一個標誌位: /* * Created on 2005-7-14 * * Java Thread Programming - Paul Hyde  * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 *  */package org.tju.msnrl.jonathan.thread.chapter8; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo *      blog.yesky.net/jonathanundersun *  * Enjoy Life with Sun! *  */public class MissedNotifyFix {        private Object proceedLock;    private boolean okToProceed;        public MissedNotifyFix(){        okToProceed = false;        proceedLock = new Object();    }        public void waitProceed() throws InterruptedException{        print("in waitProceed() - begin");                synchronized(proceedLock){            while(!okToProceed){                print("begin synchronized wait ...");                proceedLock.wait();                print("end synchronized wait ...");            }        }                print("in waitProceed() - end");    }        public void notifyProceed(){        print("in notifyProceed() - begin");                synchronized(proceedLock){            okToProceed = true;            print("begin synchronized notify ...");            proceedLock.notifyAll();            print("end synchronized notify ...");        }                print("in notifyProceed() - end");    }        public static void print(String msg){        String temp = Thread.currentThread().getName();        System.out.println(temp + " - " + msg);    }     public static void main(String[] args) {        final MissedNotifyFix mn = new MissedNotifyFix();                Runnable runA = new Runnable(){            public void run(){                try{                    Thread.sleep(1000);                    mn.waitProceed();                }catch(InterruptedException e){                    e.printStackTrace();                }            }        };                Thread threadA= new Thread(runA,"threadA");        threadA.start();                Runnable runB = new Runnable(){            public void run(){                try{                    Thread.sleep(500);                    mn.notifyProceed();                }catch(InterruptedException e){                    e.printStackTrace();                }            }        };                Thread threadB = new Thread(runB,"threadB");        threadB.start();                try{            Thread.sleep(10000);        }catch(InterruptedException e){                    }                print("interrupt thread A ...");        threadA.interrupt();    }} 輸出結果:threadB - in notifyProceed() - beginthreadB - begin synchronized notify ...threadB - end synchronized notify ...threadB - in notifyProceed() - endthreadA - in waitProceed() - beginthreadA - in waitProceed() - endmain - interrupt thread A ...  Early Notification  If a thread is notified while waiting, but the condition the thread is waiting for has not yet been met, the thread has received an early notification. An early notification can also occur if the condition is briefly met but quickly changes so it’s no longer met. This might sound strange, but early notification can happen due to subtle errors in the code (generally when an if is used instead of a while). Early notification是指:當一個等待線程被通知的時候,它等待的條件不再滿足,這時我們說,線程收到了一個early notification。Early notification在等待的條件瞬間滿足然後立刻改變不再滿足時,也會發生。通常在一個需要使用while的地方使用了if。 Early notification的代碼:/* * Created on 2005-7-14 * * Java Thread Programming - Paul Hyde  * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 *  */package org.tju.msnrl.jonathan.thread.chapter8; import java.util.*; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo *      blog.yesky.net/jonathanundersun *  * Enjoy Life with Sun! *  */public class EarlyNotify {        private List list;        public EarlyNotify(){        list = Collections.synchronizedList(new LinkedList());    }        public String removeItem() throws InterruptedException{        print("entering removeItem()...");        synchronized(list){            if(list.isEmpty()){                print("list wait ... begin");                list.wait();                print("list wait ... end");            }                        String item = (String)list.remove(0);                        print("leaveing removeItem() ...");            return "you remove " + item;        }    }        public void addItem(String item){        print("entering addItem() ...");                synchronized(list){            list.add(item);                        print("list notify ... begin");            list.notifyAll();            print("list notify ... end");        }                print("leave addItem() ...");    }        public static void print(String msg){        String temp = Thread.currentThread().getName();        System.out.println(temp + " - " + msg);    }     public static void main(String[] args) {        final EarlyNotify en = new EarlyNotify();                Runnable runA = new Runnable(){            public void run(){                try{                    String item = en.removeItem();                    print("in run() remove item " + item);                }catch(InterruptedException e1){                    print("interrupted");                }catch(Exception e2){                    print("exception" + e2.getMessage());                }                           }        };                Runnable runB = new Runnable(){            public void run(){                en.addItem("hello");            }        };                try{            Thread threadA = new Thread(runA,"threadA");            threadA.start();                        Thread.sleep(500);                        Thread threadB = new Thread(runA,"threadB");            threadB.start();                        Thread.sleep(500);                        Thread threadC = new Thread(runB,"threadC");            threadC.start();                        Thread.sleep(10000);            threadA.interrupt();            threadB.interrupt();                    }catch(InterruptedException e1){                    }catch(Exception e2){                    }            }} 輸出結果:threadA - entering removeItem()...threadA - list wait ... beginthreadB - entering removeItem()...threadB - list wait ... beginthreadC - entering addItem() ...threadC - list notify ... beginthreadC - list notify ... endthreadA - list wait ... endthreadA - leaveing removeItem() ...threadA - in run() remove item you remove hellothreadB - list wait ... endthreadC - leave addItem() ...threadB - exceptionIndex: 0, Size: 0 正確的代碼:/* * Created on 2005-7-14 * * Java Thread Programming - Paul Hyde  * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 *  */package org.tju.msnrl.jonathan.thread.chapter8; import java.util.*; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo *      blog.yesky.net/jonathanundersun *  * Enjoy Life with Sun! *  */public class EarlyNotifyFix {        private List list;        public EarlyNotifyFix(){        list = Collections.synchronizedList(new LinkedList());    }        public String removeItem() throws InterruptedException{        print("entering removeItem()...");        synchronized(list){            while(list.isEmpty()){//use while instead of if                print("list wait ... begin");                list.wait();                print("list wait ... end");            }                        String item = (String)list.remove(0);                        print("leaveing removeItem() ...");            return "you remove " + item;        }    }        public void addItem(String item){        print("entering addItem() ...");                synchronized(list){            list.add(item);                        print("list notify ... begin");            list.notifyAll();            print("list notify ... end");        }                print("leave addItem() ...");    }        public static void print(String msg){        String temp = Thread.currentThread().getName();        System.out.println(temp + " - " + msg);    }     public static void main(String[] args) {        final EarlyNotifyFix en = new EarlyNotifyFix();                Runnable runA = new Runnable(){            public void run(){                try{                    String item = en.removeItem();                    print("in run() remove item " + item);                }catch(InterruptedException e1){                    print("interrupted");                }catch(Exception e2){                    print("exception" + e2.getMessage());                }                           }        };                Runnable runB = new Runnable(){            public void run(){                en.addItem("hello");            }        };                try{            Thread threadA = new Thread(runA,"threadA");            threadA.start();                        Thread.sleep(500);                        Thread threadB = new Thread(runA,"threadB");            threadB.start();                        Thread.sleep(500);                        Thread threadC = new Thread(runB,"threadC");            threadC.start();                        Thread.sleep(10000);            threadA.interrupt();            threadB.interrupt();                    }catch(InterruptedException e1){                    }catch(Exception e2){                    }            }} 輸出結果:threadA - entering removeItem()...threadA - list wait ... beginthreadB - entering removeItem()...threadB - list wait ... beginthreadC - entering addItem() ...threadC - list notify ... beginthreadC - list notify ... endthreadA - list wait ... endthreadA - leaveing removeItem() ...threadA - in run() remove item you remove hellothreadB - list wait ... endthreadB - list wait ... beginthreadC - leave addItem() ...threadB - interrupted  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.