zoukankan      html  css  js  c++  java
  • 我的java之路(一):锁定、等待和通知——要操作同一对象

    最近在听java的课,老师的PPT上有一个线程同步的例子,是要利用synchronized、wait和notify来实现。我把它输入到电脑并且补全了所有罗杰。运行之后发现它没有按照预想的输出结果。琢磨了好久之后,才找到法门。

    代码如下:

    一个栈的模拟:

    View Code
    package ThreadDemo;
    
    import java.util.*;
    
    public class StackDemo {
        private Vector buffer = new Vector(400, 200);
        public synchronized char pop()
        {
            char c;
            
            while(buffer.size() == 0)
            {
                try
                {
                    this.wait();
                }
                catch(InterruptedException e){}
            }
            
            Object top = buffer.remove(buffer.size() - 1);
            c = (Character)top;
            
            return c;
        }
        
        public synchronized void push(char c)
        {
            this.notify();
            Character charObj = new Character(c);
            buffer.addElement(charObj);
        }
    }

    两个线程:

    View Code
    package ThreadDemo;
    
    public class ThreadPush implements Runnable {
        
        StackDemo stack = new StackDemo();    
        public void run()
        {
            char c;
            for(int i=0; i < 200; i++)
            {
                c = (char)(Math.random()*26 + 'A');
                stack.push(c);
                try
                {
                    Thread.sleep(300);
                }
                catch(InterruptedException e){}
            }
        }
    }

    和:

    View Code
    package ThreadDemo;
    
    import java.util.*;
    
    public class ThreadPop implements Runnable {
        
        StackDemo stack = new StackDemo();    
        public void run()
        {
            char c;
            for(int i = 0; i < 200; i ++)
            {
                c = stack.pop();
                System.out.println(c);
                
                try
                {
                    Thread.sleep(300);
                }
                catch(InterruptedException e){}
            }
        }
    }

    主函数:

    View Code
    package ThreadDemo;
    public class ThreadDemoMain {
            public static void main(String[] args) {            
            ThreadPush pushObject = new ThreadPush();
            Thread thread1 = new Thread(pushObject);
            thread1.start();
            
            ThreadPop popObject = new ThreadPop();
            Thread thread2 = new Thread(popObject);
            thread2.start();
        }
    }

    执行的情况是:pop线程一旦wait就再也醒不来了;push线程倒是一直在正常工作。这我就很纳闷,push进去那么多,而且notify语句也执行了,pop线程始终跟喝醉了似的,没有任何反应。无奈之下,我把PPT又翻出来,重新看wait的用法。发现它说,x.wait()之后,线程就进入了x对象的等待池。我的程序里边用的是,this.wait,this是谁?不就是StackDemo的实例嘛?。。。哦,我明白了,两个线程使用了两个不相同的StackDemo实例。这。。。

    修改之后的代码:

    栈模拟的代码没变。。。

    两个线程:(在构造函数中要求传入StackDemo的实例,而不是自己生成!!!)

    View Code
    package ThreadDemo;
    
    public class ThreadPush implements Runnable {
        
        StackDemo stack = null;
        
        public ThreadPush(StackDemo stack)
        {
            this.stack = stack;
        }
        
        public ThreadPush(){}
        
        public void run()
        {
            char c;
            for(int i=0; i < 200; i++)
            {
                c = (char)(Math.random()*26 + 'A');
                stack.push(c);
                try
                {
                    Thread.sleep(300);
                }
                catch(InterruptedException e){}
            }
        }
    }

    和:

    View Code
    package ThreadDemo;
    
    import java.util.*;
    
    public class ThreadPop implements Runnable {
        
        StackDemo stack = null;
        
        public ThreadPop(StackDemo stack)
        {
            this.stack = stack;
        }
        public ThreadPop(){}
        
        public void run()
        {
            char c;
            for(int i = 0; i < 200; i ++)
            {
                c = stack.pop();
                System.out.println(c);
                
                try
                {
                    Thread.sleep(300);
                }
                catch(InterruptedException e){}
            }
        }
    }

    主函数:(创建一个StackDemo实例,并且传入两个线程!!!)

    View Code
    package ThreadDemo;
    
    public class ThreadDemoMain {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            
            StackDemo stack = new StackDemo();
            
            ThreadPush pushObject = new ThreadPush(stack);
            Thread thread1 = new Thread(pushObject);
            thread1.start();
            
            ThreadPop popObject = new ThreadPop(stack);
            Thread thread2 = new Thread(popObject);
            thread2.start();
        }
    }

    嗒嗒,程序终于正常工作了,乖乖地push进去200个字符,并且在pop之后输出。

    这个故事告诉我们,上锁啊,等待啊,通知啊,都要对相同的对象才行。否则,就会出现我遇到的情况,一个按规定发通知,另一个死等,啥也没等到。

  • 相关阅读:
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(28)-系统小结
    用谷歌浏览器来当手机模拟器
    解决PHP使用CVS导出Excel乱码问题
    Linux系统中关于Sqlite3中文乱码问题及解决办法
    解决excel日期变成数字的问题
    基于IE的多标签的浏览器-世界之窗2.4
    Thinkphp 获取所有子分类或父分类ID
    PhpExcel 删除默认的Sheet
    Mysql 创建表时错误:Tablespace for table `tablexx` exists. Please DISCARD the tablespace before IMPORT.
    关于ThinkPhp中getField方法存在的问题
  • 原文地址:https://www.cnblogs.com/ceachy/p/2549259.html
Copyright © 2011-2022 走看看