首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 请问如下的多线程代码为何出现异常? [已结帖,结帖人:tteesstt]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tteesstt
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-07-10 19:39:19 楼主
    Java code
    public class MyTest { public static void main(String[] args) throws Exception { new TestThread().start(); new TestThread().start(); Thread.sleep(1000); System.out.println("Doing something..."); synchronized (lock) { lock = false; // 语句1 lock.notifyAll(); // 语句2 } } static volatile Boolean lock = true;; } class TestThread extends Thread { @Override public void run() { synchronized (MyTest.lock) { while (MyTest.lock) { try { MyTest.lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(getId()); } } }


    输出为
    Java code
    Doing something... Exception in thread "main" java.lang.IllegalMonitorStateException at java.lang.Object.notifyAll(Native Method) at MyTest.test(MyTest.java:13) at MyTest.main(MyTest.java:3)


    如果把语句1和语句2调换一下就正常了。
    大家给诊断一下,到底是为什么?
    该帖子于2008-07-11 05:15:37被版主修改
    200  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • java2000_net_test
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 19:39:221楼 得分:1
    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【tteesstt】截止到2008-07-10 19:39:17的历史汇总数据(不包括此帖):
    发帖的总数量:97                      发帖的总分数:5700                    每贴平均分数:58                     
    回帖的总数量:62                      得分贴总数量:5                        回帖的得分率:8%                     
    结贴的总数量:97                      结贴的总分数:5700                   
    无满意结贴数:0                        无满意结贴分:0                       
    未结的帖子数:0                        未结的总分数:0                       
    结贴的百分比:100.00%              结分的百分比:100.00%                 
    无满意结贴率:0.00  %              无满意结分率:0.00  %                 
    敬礼!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • imA
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 19:46:462楼 得分:2
    你的lock都没定义啊,竟然编译过去了?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sagezk
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 19:54:373楼 得分:0
    引用 2 楼 imA 的回复:
    你的lock都没定义啊,竟然编译过去了?


    他那 lock 在 MyTest 中:static volatile Boolean lock = true;
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • java2000_net
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

      2

    发表于:2008-07-10 19:59:144楼 得分:30
    奇怪,我刚才特意测试了一下,如果那个lock和条件分开,则可以,否则不行。
    Java code
    public class MyTest { public static void main(String[] args) throws Exception { new TestThread().start(); new TestThread().start(); Thread.sleep(1000); System.out.println("Doing something..."); synchronized (lock) { lock.notifyAll(); lock.wait(); condition = true; // 语句1 lock.notifyAll(); // 语句2 } System.exit(0); } static volatile Object lock = new Object(); static volatile Boolean condition = false;; } class TestThread extends Thread { @Override public void run() { synchronized (MyTest.lock) { while (!MyTest.condition) { try { MyTest.lock.wait(); System.out.println(getId()); MyTest.lock.notifyAll(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(getId()); } } }

    不过我也不清楚为何条件和锁用一个对象为何不行?难道???????那个赋值的问题,
    lock = false; // 语句1
    重新生成了一个新的对象吗???造成锁异常
    我去测试看看!!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • java2000_net
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

      2

    发表于:2008-07-10 20:03:495楼 得分:0
    我用了一个可以修改内容的类,StringBuilder,同时使用了新的判断条件.length()==0;
    Java code
    public class MyTest { public static void main(String[] args) throws Exception { new TestThread().start(); new TestThread().start(); Thread.sleep(1000); System.out.println("Doing something..."); synchronized (lock) { lock.append(1); // 语句1 lock.notifyAll(); // 语句2 } } static volatile StringBuilder lock = new StringBuilder();; } class TestThread extends Thread { @Override public void run() { synchronized (MyTest.lock) { while (MyTest.lock.length() == 0) { try { MyTest.lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(getId()); } } }

    问题难道真的是那个吗?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tianyasuifeng
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 20:09:026楼 得分:1
    up
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sagezk
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 20:31:257楼 得分:30
    Java code
    public static final Boolean TRUE = new Boolean(true); public static final Boolean FALSE = new Boolean(false); public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }


    lock = false; 不会生成新对象,应该是这儿的原因。

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sagezk
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 20:33:428楼 得分:0
    Java code
    lock = false; //这句已经改变了 lock 的引用 lock.notifyAll(); //再通知也没用
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • LexChen
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 20:44:379楼 得分:30
    应该就是赋值的问题!
    查看Object类的源代码,关于notifyAll的说明指向去参考notify的说明,里面说道:
    This method should only be called by a thread that is the owner of this object's monitor
    是对象的monitor有三种方式:
        * <li>By executing a synchronized instance method of that object.
        * <li>By executing the body of a <code>synchronized </code> statement
        *    that synchronizes on the object.
        * <li>For objects of type <code>Class, </code> by executing a
        *    synchronized static method of that class.
    这个赋值与Java的对象类型有关,当对一个Boolean赋值为一个boolean型值时,导致原来的lock
    所指的对象成为了一个新的boolean的包装类,这样前面的synchronized(lock)就失效了,所以报
    除了异常,尝试下面的例子,我们对一个Object调用了一系列的方法来做,lock指向的对象并没有发生
    变化,所以synchronized仍然有效,就不会报错了,

    不过,只是觉得好像是这样,呵呵。


    请尝试一下的代码,运行无误
    Java code
    public class MyTest { public static void main(String[] args) throws Exception { new TestThread().start(); new TestThread().start(); Thread.sleep(1000); System.out.println("Doing something..."); synchronized (lock) { lock.setIII(2); lock.notifyAll(); } System.exit(0); } static volatile AAA lock = new AAA(1); } class TestThread extends Thread { @Override public void run() { synchronized (MyTest.lock) { while (MyTest.lock.getIII()==1) { try { MyTest.lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(getId()); } } } class AAA { int iii; public AAA(int i){ iii = i; } public void setIII(int i){ iii = i; } public int getIII(){ return iii; } }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Ant_Yan
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 21:44:1410楼 得分:0
    肯定是赋值问题,赋值之后新建了一个lock对象,赋值完毕notifyAll回到两个线程的wait方法继续走,while循环推出,然后接着马上要推出sychronized块,这个时候lock对象的MonitorState异常所以程序退出了

    因为每次进入sychronized块要获得对象的monitor并计数加1,退出的时候计数减1,如果这个计数对不上就会报错!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sagezk
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 22:48:3311楼 得分:0
    引用 10 楼 Ant_Yan 的回复:
    肯定是赋值问题,赋值之后新建了一个lock对象,赋值完毕notifyAll回到两个线程的wait方法继续走,while循环推出,然后接着马上要推出sychronized块,这个时候lock对象的MonitorState异常所以程序退出了

    因为每次进入sychronized块要获得对象的monitor并计数加1,退出的时候计数减1,如果这个计数对不上就会报错!


    看源码,不会创建新 Boolean 对象。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sagezk
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 22:50:0812楼 得分:0
    始终是两个分别包装了 true 和 false 的 Boolean 在那儿折腾。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yirentianran
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 23:05:5513楼 得分:1
    迷糊
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • loveyunwt
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 23:08:0314楼 得分:1
    lock = false; //这句已经改变了 lock 的引用
    lock.notifyAll(); //再通知也没用
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • loujianchengdd
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 23:12:5515楼 得分:1
    up
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bao110908
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

      4

    发表于:2008-07-10 23:35:0316楼 得分:30
    自动装箱导致的对象变动

    值为 true 的 Boolean 对象监视范围内并没有进行等待的线程,
    所以就抛出了 IllegalMonitorStateException 的异常。

    只要把改变值之前的 lock 引用对象再赋给一个临时的变量,由
    这个临时变量来通知就行了,呵呵。

    Java code
    synchronized (lock) { Boolean b = lock; lock = false; b.notifyAll(); }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bao110908
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

      4

    发表于:2008-07-10 23:36:5917楼 得分:0
    晕,写错了,更正!

    值为 true 的 Boolean 对象监视范围内并没有进行等待的线程,

    改为:

    值为 false 的 Boolean 对象监视范围内并没有进行等待的线程,
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bao110908
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

      4

    发表于:2008-07-10 23:39:1118楼 得分:0
    对于布尔对象来说,甚至可以改成:

    Java code
    synchronized (lock) { lock = false; Boolean.TRUE.notifyAll(); }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sagezk
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-10 23:53:5219楼 得分:1
    对,是火龙果这意思。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wensheng_zh2007
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 00:39:0320楼 得分:1
    小弟学习了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • babyvox1999
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 08:03:0021楼 得分:1
    引用 20 楼 wensheng_zh2007 的回复:
    小弟学习了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • microsoftzxw
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 08:34:3122楼 得分:0
    该回复于2008-07-11 12:12:58被版主删除
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Ant_Yan
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 08:38:1123楼 得分:20
    引用 17 楼 bao110908 的回复:

    值为 false 的 Boolean 对象监视范围内并没有进行等待的线程,


    那么到底有没有两个Boolean对象呢?
    我认为值为true和值为false的Boolean对象分别拥有自己的Monitor(监视器),所以正如火龙果前辈说的,为false的Boolean对象监视器替换掉true的监视器之后,无法退出sychronized块,因为曾经读过JVM官方规范:

    每次进入sychronized块监视器计数要加1,退出的时候要减1,如果最终为0才能正常退出,否则抛出MonitorState异常。而当初进入sychronized加1的是true的Boolean对象的监视器,退出的时候计数减1的却是为false的Boolean的监视器
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • xufly2008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 08:43:3824楼 得分:10
    synchronized (lock) {
            lock = false;
            lock.notifyAll();
        }
    所有的封装类都是只读的,所以 lock = false; 将返回一个新的对象,而当前线程获得的是原对象的锁,
    所以在新的lock对象上调用notifyAll导致IllegalMonitorStateException,与另外两个线程无关,
    如果一个线程没有获得某个对象的锁而调用它的notifyAll将导致IllegalMonitorStateException。
            个人理解,望指证。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • gjw19851214
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 08:51:2325楼 得分:1
    正在学习!!向各位前辈学习!!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fellowcheng
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 08:56:3126楼 得分:1
    学习
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhuyx808
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 08:57:3827楼 得分:1
    额~~~~~~·
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • LexChen
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 09:02:2728楼 得分:2
    昨天我回了好大一篇啊,发贴成功,怎么现在看不见了 :( , 痛苦……
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jishu_vip
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 09:03:4029楼 得分:1
    不是很明白
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • LexChen
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 09:04:3030楼 得分:1
    晕,发完这篇就看到了,难道是论坛有问题,刚才只显示到6楼,再发了一遍就到28楼了,困惑中,呵呵
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yetaodiao
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 09:12:1231楼 得分:1
    lock和条件分开
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fxltsblsds
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 09:26:3732楼 得分:1
    对象的监视范围是什么?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • havelock
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 09:37:1533楼 得分:0
    他用的包装类 Boolean,会改变引用.直接锁 Boolean.class试试,应该不会出异常.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • havelock
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 09:48:2434楼 得分:3
    引用 33 楼 havelock 的回复:
    他用的包装类 Boolean,会改变引用.直接锁 Boolean.class试试,应该不会出异常.


    更正,还是会出现异常,原因,对象不同.

    控制台输出赋值前后的 hashcode 为:

    Doing something...
    1231
    1237
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fuqd273
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 09:59:4635楼 得分:1
    mark
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lja7912aaa
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 10:11:5936楼 得分:1
    学习 false和true应该是2个对象

    引用 7 楼 sagezk 的回复:
    Java code
        public static final Boolean TRUE = new Boolean(true);

        public static final Boolean FALSE = new Boolean(false);

        public static Boolean valueOf(boolean b) {
            return (b ? TRUE : FALSE);
        }


    lock = false; 不会生成新对象,应该是这儿的原因。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jingulang
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 10:13:4937楼 得分:1
    学习了  volatile 关键字我还没弄明白。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lja7912aaa
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 10:38:1838楼 得分:2
    static volatile Boolean lock = true;
    lock已经同步  这个volatile不用加吧
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yinfei456
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 11:29:5339楼 得分:1
    实在不明白这段代码,又没有好心人给仔细讲解一下,运行顺序阿?我看了半天都不明白
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • oogamiyiqilou
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 11:42:5740楼 得分:1
    我也是不太明白
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jingulang
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 11:53:3441楼 得分:1
    me too.....
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jingulang
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 11:57:3342楼 得分:1
    lock.notifyAll();  这句十分不解

    谁解释解释`~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • daybybyby
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 15:43:4843楼 得分:10
      lock = false; // 语句1
      lock.notifyAll(); // 语句2
    这种情况下,必然出错阿。。。lock已经是一个新对象了,而lock.notifyAll()在新对象上没有被同步。所以current thread not owner。
    换个顺序以后,在原来对象上notifyAll()了lock才变成新对象,所以没有错了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • daybybyby
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 15:57:0444楼 得分:0
    object的notify, notifyall, wait方法必须是被synchronize的,如果一个新对象没有被synchronize的时候调用这些方法就
    会current thread not owner。比如楼主问得
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wangjt18
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 16:24:3245楼 得分:2
    up
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • denverbenjamin2000
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 16:39:2146楼 得分:5
    我在写一个程序的时候也出现类似问题:
    参见http://topic.csdn.net/u/20080710/18/9e9cdcfd-1b8c-4203-b6ba-27a2d8b8b2df.html
            synchronized (GlobalControl.isEnd) {
                GlobalControl.isEnd=true;
                GlobalControl.isEnd.notify();
            }

    中,GlobalControl.isEnd=true;将使得GlobalControl.isEnd指向一个与
    synchronized (GlobalControl.isEnd) 截然不同的对象,当然出问题了。


    Exception in thread "pool-1-thread-20" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at thread1.ParaNull.LogicalProcess.run(LogicalProcess.java:367)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
    at java.lang.Thread.run(Thread.java:619)
    错误
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • stupid_boy2007
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 17:46:1047楼 得分:2
    大哥你真猛,我认得你老紫竹啊。哈哈~~

    本人电脑没联网,在网吧上,没仔细看。

    接一分~~~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yunbaixingxing
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-11 20:44:2648楼 得分:0
    学习学习........
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • houbeijing
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-12 09:36:0249楼 得分:0
    hao
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • defengaoshou2008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-12 12:43:0850楼 得分:0
    看帖
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jfwcn
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-12 15:13:4651楼 得分:0
    看贴
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • cainiaoqiuzhu
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-12 16:32:2252楼 得分:0
    rq看帖
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kugou1314
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-12 16:45:3153楼 得分:0
    很火爆的帖子
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • l999358
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-12 16:49:0054楼 得分:0
    用C语言或者汇编吧,我用C从来没出现过这么闹心的事,我总是知道自己的程序都在干什么,要干什么,这多闹心,还要猜自己的程序到底干过什么--!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ghyghost
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-12 19:53:4255楼 得分:0
    JAVA的多线程的确很累,太多细节的东西
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dlingt
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-12 21:34:0756楼 得分:0
    对像被创建了一个,引用变了, 没有啥好说的,这是底层机制
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yuan_979039976
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-13 00:53:5657楼 得分:0
    Thread.sleep(1000);
    会产生中断异常
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lmlnmm0752
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-13 10:55:4658楼 得分:0
    老紫竹真是高手,lock=new object();
    当lock要成为boolean时,是要申明成look=new Boolean(Boolean.FALSE);
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • laohujizuobiqi
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-13 17:33:0259楼 得分:0
    该回复于2008-07-14 15:01:24被版主删除
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • denverbenjamin2000
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-14 03:50:3860楼 得分:0
    我们在搞线程开发前,应该好好学习一下IBM developerwork上面已有的一些东西
    不要重新分配被锁定对象的对象引用
    developerWorks




    Peter Haggar, 高级软件工程师, IBM

    2000 年 10 月 01 日

        编者按:编者按:本文是从“Practical Java”( Addison-Wesley 出版)一书节选而来的。您可以从 Borders.com 订购该书。请阅读我们对作者 Peter Haggar 的 采访。

    synchronized 关键字锁定对象。对象是在 synchronized 代码内部被锁定的,这一点对此对象以及您对其对象引用所作的更改意味着什么呢?对一个对象作同步处理只锁定该对象。但是,必须注意不要重新分配被锁定对象的对象引用。那么如果这样做会发生什么情况呢?请考虑下面这段代码,它实现了一个 Stack:

    class Stack
    {
      private int StackSize = 10;
      private int[] intArr = new int[stackSize];
      private int index;          //Stack 中的下一个可用位置。
      public void push(int val)
      {
        synchronized(intArr) {
          //如果已满,则重新分配整数数组(即我们的 Stack)。
          if (index == intArr.length)
          {
            stackSize *= 2;
            int[] newintArr == new int[stackSize];
            System.arraycopy(intArr, 0, newintArr, 0, intArr.length);
            intArr = newintArr;
          }
          intArr[index] == val;
          index++;
        }
      }
      public int pop()
      {
        int retval;
        synchronized(intArr) {
          if (index > 0)
          {
            retval = intArr[index-1];      //检索值,
            index--;                      //并使 Stack 减少 1 个值。
            return retval;
          }
        }
        throw new EmptyStackException();
      }
      //...
    }


    这段代码用数组实现了一个 Stack。创建了一个初始大小为 10 的数组来容纳整数值。此类实现了 push 和 pop 方法来模拟 Stack 的使用。在 push 方法中,如果数组中没有更多的空间来容纳压入的值,则数组被重新分配以创建更多的存储空间。(故意没有用 Vector 来实现这个类。 Vector 中不能储存基本类型。)

    请注意,这段代码是要由多个线程进行访问的。push 和 pop 方法每次对该类的共享实例数据的访问都是在 synchronized 块内完成的。这样就保证了多个线程不能并发访问此数组而生成不正确的结果。

    这段代码有一个主要的缺点。它对整数数组对象作了同步处理,而这个数组被 Stack 类的 intArr 所引用。当 push 方法重新分配此整数数组时,这个缺点就会显露出来。当这种情况发生时,对象引用 intArr 被重新指定为引用一个新的、更大的整数数组对象。请注意,这是在 push 方法的 synchronized 块执行期间发生的。此块针对 intArr 变量引用的对象进行了同步处理。因此,在这段代码内锁定的对象不再被使用。请考虑以下的事件序列:

      1. 线程 1 调用 push 方法并获得 intArr 对象的锁。

      2. 线程 1 被线程 2 抢先。

      3. 线程 2 调用 pop 方法。此方法因试图获取当前线程 1 在 push 方法中持有的同一个锁而阻塞。

      4. 线程 1 重新获得控制并重新分配数组。 intArr 变量现在引用一个不同的变量。

      5. push 方法退出并释放它对原来的 intArr 对象的锁。

      6. 线程 1 再次调用 push 方法并获得新 intArr 对象的锁。

      7. 线程 1 被线程 2 抢先。

      8. 线程 2 获得旧 intArr 对象的对象锁并试图访问其内存。

    现在线程 1 持有由 intArr 引用的新对象的锁,线程 2 持有由 intArr 引用的旧对象的锁。因为两个线程持有不同的锁,所以它们可以并发执行 synchronized push 和 pop 方法,从而导致错误。很明显,这不是所希望的结果。

    这个问题是因 push 方法重新分配被锁定对象的对象引用而造成的。当某个对象被锁定时,其他线程可能在同一个对象锁上被阻塞。如果将被锁定对象的对象引用重新分配给另一个对象,其他线程的挂起锁则是针对代码中已不再相关的对象的。

    您可以这样修正这段代码,去掉对 intArr 变量的同步,而对 push 和 pop 方法进行同步。通过将 synchronized 关键字添加为方法修饰符即可实现这一点。正确的代码如下所示:

    class Stack
    {
      //与前面相同...
      public synchronized void push(int val)
      {
        //如果为空,则重新分配整数数组(即我们的 Stack)。
        if (index == intArr.length)
        {
          stackSize *= 2;
          int[] newintArr = new int[stackSize];
          System.arraycopy(intArr, 0, newintArr, 0, intArr.length);
          intArr = newintArr;
        }
        intArr[index]= val;
        index++;
      }
      public synchronized int pop()
      {
        int retval;
        if (index > 0)
        {
          retval = intArr[index-1];
          index--;
          return retval;
        }
        throw new EmptyStackException();
      }
    }


    这个修改更改了实际上获取的锁。获取的锁是针对为其调用方法的对象的,而不是锁定 intArr 变量所引用的对象。因为获取的锁不再针对 intArr 所引用的对象,所以允许代码重新指定 intArr 对象引用。


    关于作者



    Peter Haggar 是 IBM 的高级软件工程师。他目前正在研究新兴的 Java 和因特网技术,并且是 IBM 实时 Java 参考实现的项目主持人。他有丰富的编程经验,从事过开发工具、类库和操作系统等方面的工作。在许多行业研讨会上,他也经常就 Java 和其他技术作技术性发言。他于 1987 年在纽约获得 Clarkson 大学计算机科学学士学位。可以通过 haggar@us.ibm.com 与他联系
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhiguo2008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-14 12:39:5661楼 得分:0
    引用 60 楼 denverbenjamin2000 的回复:
    我们在搞线程开发前,应该好好学习一下IBM developerwork上面已有的一些东西
    不要重新分配被锁定对象的对象引用
    developerWorks


    Peter Haggar, 高级软件工程师, IBM

    2000 年 10 月 01 日

        编者按:编者按:本文是从“Practical Java”( Addison-Wesley 出版)一书节选而来的。您可以从 Borders.com 订购该书。请阅读我们对作者 Peter Haggar 的 采访。

    synchronized 关键字锁定对象。对象是在 syn…

      ...
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • crcr
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-14 17:19:0362楼 得分:0
    ok以后再看
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tl0352118
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-15 13:30:2763楼 得分:0
    学习,mark
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kuku12bing
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-07-16 22:28:5564楼 得分:0
    回帖是一种美德!传说每天回帖即可获得 10 分可用分回帖是一种美德!传说每天回帖即可获得 10 分可用分回帖是一种美德!传说每天回帖即可获得 10 分可用分
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • brz97
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-07 15:57:2865楼 得分:0
    明白了,引用的问题
    学习了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jason_zzw
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-07 17:10:5866楼 得分:0
    引用 18 楼 bao110908 的回复:
    对于布尔对象来说,甚至可以改成:

    Java codesynchronized(lock) {
            lock=false;
            Boolean.TRUE.notifyAll();
        }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lzycsd
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-11 17:57:0867楼 得分:0
    mark
    修改 删除 举报 引用 回复