快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

Java Thread Programming 1.8.2 - Inter-thread Communication

 
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() - begin
threadB - begin synchronized notify ...
threadB - end synchronized notify ...
threadB - in notifyProceed() - end
threadA - in waitProceed() - begin
threadA - 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() - begin
threadB - begin synchronized notify ...
threadB - end synchronized notify ...
threadB - in notifyProceed() - end
threadA - in waitProceed() - begin
threadA - in waitProceed() - end
main - 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 ... begin
threadB - entering removeItem()...
threadB - list wait ... begin
threadC - entering addItem() ...
threadC - list notify ... begin
threadC - list notify ... end
threadA - list wait ... end
threadA - leaveing removeItem() ...
threadA - in run() remove item you remove hello
threadB - list wait ... end
threadC - 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 ... begin
threadB - entering removeItem()...
threadB - list wait ... begin
threadC - entering addItem() ...
threadC - list notify ... begin
threadC - list notify ... end
threadA - list wait ... end
threadA - leaveing removeItem() ...
threadA - in run() remove item you remove hello
threadB - list wait ... end
threadB - list wait ... begin
threadC - leave addItem() ...
threadB - interrupted




返回类别: 教程
上一教程: JAVA写的四则混合运算
下一教程: JAVA反射技术(二)

您可以阅读与"Java Thread Programming 1.8.2 - Inter-thread Communication"相关的教程:
· Java Thread Programming 1.8.4 - Inter-thread Communication
· Java Thread Programming 1.8.1 - Inter-thread Communication
· Java Thread Programming 1.8.3 - Inter-thread Communication
· Java Thread Programming 1.7 - Concurrent Access to Objects and Variables
· Java中ThreadLocal的设计与使用
    微笑服务 优质保证 索取样品