A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 冉世友 中级黑马   /  2013-1-1 18:25  /  2087 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

看张老师的线程范围内的共享变量,下面一段代码运行有时会出现
空指针异常,分析了半天不知道咋回事。。。
  1. package cn.itcast;

  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import java.util.Random;

  5. public class ThreadScopeDataShare {

  6.         private static int data = 0;
  7.         private static Map<Thread, Integer> threadData= new HashMap<Thread, Integer>();
  8.         public static void main(String[] args) {
  9.                 for(int i=0; i<2; i++){
  10.                         new Thread(new Runnable(){
  11.                                 @Override
  12.                                 public void run() {
  13.                                          int data = new Random().nextInt(9);
  14.                                         threadData.put(Thread.currentThread(), data);
  15.                                         System.out.println(Thread.currentThread().getName() + " has " +
  16.                                                         "put data " + data);
  17.                                        
  18.                                         new A().get();
  19.                                         new B().get();
  20.                                 }
  21.                         }).start();
  22.                 }
  23.                
  24.                 try {
  25.                         Thread.sleep(1000);
  26.                 } catch (InterruptedException e) {
  27.                        
  28.                         e.printStackTrace();
  29.                 }
  30.                 System.out.println(data);
  31.         }
  32.        
  33.         //定义模块A,去获取当前线程的数据data
  34.         static class A {
  35.                 int data = threadData.get(Thread.currentThread());
  36.                 public void get(){
  37.                         System.out.println("A from " + Thread.currentThread().getName()
  38.                                         + " get data " + data);
  39.                 }
  40.         }
  41.        
  42.         //定义模块B,去获取当前线程的数据data
  43.         static class B {
  44.        int data = threadData.get(Thread.currentThread());
  45.        public void get(){
  46.              System.out.println("B from " + Thread.currentThread().getName()
  47.                                                + " get data " + data);
  48.                 }
  49.         }
  50. }
复制代码
有一次运行结果:
  1. Thread-1 has put data 2
  2. Thread-0 has put data 1
  3. A from Thread-0 get data 1
  4. Exception in thread "Thread-1" java.lang.NullPointerException
  5.            at cn.itcast.ThreadScopeDataShare$A.<init>(ThreadScopeDataShare.java:43)
  6.            at cn.itcast.ThreadScopeDataShare$1.run(ThreadScopeDataShare.java:26)
  7.            at java.lang.Thread.run(Thread.java:662)
  8. B from Thread-0 get data 1
  9. 0
复制代码

评分

参与人数 1技术分 +1 收起 理由
崔政 + 1

查看全部评分

8 个回复

正序浏览
感觉吧,张老师讲的太刁,但很多东西实际上用不到。
回复 使用道具 举报
冉世友 发表于 2013-1-2 22:42
哥们,你多运行几次试试,我就是没事多运行了几次才发现的这个问题。。 ...

看你包名还以为你在传智呢
回复 使用道具 举报
何伟 发表于 2013-1-1 23:31
楼主也在传智????????????????

没呢,正在学习准备入学考试
回复 使用道具 举报
张森 发表于 2013-1-2 03:42
楼主 你的代码在我们这里运行没有任何问题,运行结果如下
Thread-0 has put data 3
Thread-1 has put data  ...

哥们,你多运行几次试试,我就是没事多运行了几次才发现的这个问题。。
回复 使用道具 举报
楼主 你的代码在我们这里运行没有任何问题,运行结果如下
Thread-0 has put data 3
Thread-1 has put data 3
A from Thread-0 get data 3
A from Thread-1 get data 3
B from Thread-0 get data 3
B from Thread-1 get data 3
0

所以楼主你要确定 你是每次都有这个问题 还是偶尔出现这个问题   还有就是你可以把随机数那里先写死 看看具体的过程
不过根据你的异常代码也可以看出  是已经打印了一次A from Thread-0 get data 1了  说明是执行过一次的,
然后at cn.itcast.ThreadScopeDataShare$A.<init> 看字面意思应该是在第二个线程执行到new A那里出错了。
然后我们看A类里面  但不管是在A或者B里面  的threadData.get(Thread.currentThread());还是Thread.currentThread().getName() 都不应该有NullPointerException
因为我这来确实没有问题 所以现在也定位不了问题所在  估计是线程机制上面有某方面 我们没考虑到  你可以加我QQ2637168864我们讨论 共同学习
还有楼上叫你用DEBUG模式  我想说Debug是你以后必学的   但对于像线程这来的代码用Debug还不如用System.out,因为像游戏服务器这样的代码,里面有很多线程 如果用DEBUG的话  你会找不到方向的。   我也新人  以后有不会的地方 多多指教

评分

参与人数 1技术分 +1 收起 理由
崔政 + 1

查看全部评分

回复 使用道具 举报
楼主也在传智????????????????
回复 使用道具 举报
王少雷 发表于 2013-1-1 19:20
这种写法基本不会用到,把线程作为一个类型,当作一个键KEY 放到MAP 里面?
本来 集合是 处理数据用的,并 ...

不太明白。。。
加个Dug是什么,没学到。。。
回复 使用道具 举报
这种写法基本不会用到,把线程作为一个类型,当作一个键KEY 放到MAP 里面?
本来 集合是 处理数据用的,并不是,键KEY只是一个标识。
线程只是作为,处理共享数据用的。
本来就不是很搭配。
而且线程存在一个执行权的问题,如果一个线程没执行权,你放入到MAP 集合 会是什么现象?
加个DUG走一下。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马