黑马程序员技术交流社区

标题: 线程共享问题 [打印本页]

作者: 黑马高明辉    时间: 2012-7-26 03:59
标题: 线程共享问题
package _7_26;

import java.util.Random;

public class ThreadScopeShareData2 {

        private static int data = 0;
//        private static Map<Thread, Integer> threadData = new HashMap<Thread, Integer>();
        public static void main(String[] args) {
                for(int i=0;i<2;i++){
                        new Thread(new Runnable(){
                                @Override
                                public void run() {
                                         data = new Random().nextInt();
                                        System.out.println(Thread.currentThread().getName()
                                                        + " has put data :" + data);
//                                        threadData.put(Thread.currentThread(), data);
                                        new A().get();
                                        new B().get();
                                }
                        }).start();
                }
                new Thread(new Runnable(){
                        @Override
                        public void run() {
                                 data = new Random().nextInt();
                                System.out.println(Thread.currentThread().getName()
                                                + " has put data :" + data);
//                                threadData.put(Thread.currentThread(), data);
                                new A().get();
                                new B().get();
                        }
                }).start();
        }
       
        static class A{
                public void get(){
//                        int data = threadData.get(Thread.currentThread());
                        System.out.println("A from " + Thread.currentThread().getName()
                                        + " get data :" + data);
                }
        }
       
        static class B{
                public void get(){
//                        int data = threadData.get(Thread.currentThread());                       
                        System.out.println("B from " + Thread.currentThread().getName()
                                        + " get data :" + data);
                }               
        }
}
for循环里的两个线程为什么生成的随机数都一样??
在for循环外面新建一个线程,却能生成不同的随机数?谁给解释一下,这个很蹊跷。
---------------运行结果:------------------
Thread-0 has put data :1500315473
Thread-1 has put data :1500315473
Thread-2 has put data :445127673
A from Thread-0 get data :445127673
A from Thread-2 get data :445127673
A from Thread-1 get data :445127673
B from Thread-1 get data :445127673
B from Thread-2 get data :445127673
B from Thread-0 get data :445127673
------------------------------------------------
就看前三行,前两个线程产生的随机数和后一个不同,为什么啊?按理说应该是三个都不同才对,前两个相同,还能是因为for循环里的两个线程顺便就把变量共享了么??
作者: 侯宪博    时间: 2012-7-26 06:22
首先要说到java里面的随机数是伪随机数
如果没有设种子seed,则自动选择当前的系统时间毫秒作为种子,种子为48bits
    public Random() { this(System.currentTimeMillis()); }
如果自己设置了种子,用如下公式计算:
   this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);


很明显你的是用的系统的毫秒作为种子
for循环在瞬间创建了两个线程
获取系统时间的时候由于cpu的运行速度过快或者多核心
时间差要远远小于1毫秒
有两种办法可以证明这一点
第一种把你的for循环多循环几次多创建几个线程
一方面拉开时间差,一方面让cpu降低对每个线程的执行效率
第二种就是在for循环中加入sleep()
但是要注意不要直接加sleep()因为就算直接加了sleep()他们只会影响俩个个线程的执行时间
而不会影响线程的创建时间,因为for循环所处的线程是主线程
但是,你可以利用for循环的循环变量i来改变sleep的睡眠时间
先定义一个静态i用作for循环的循环变量,然后在线程获取随机值之前加入sleep(1000*(i+1))
这样虽不可以影响线程创建时间,却可以影响获取随机值的时间
希望可以对你有所帮助。。。
作者: 王程    时间: 2012-8-3 22:11
我的运行结果是
Thread-0 has put data :-440780971
Thread-1 has put data :938847031
A from Thread-0 get data :938847031
Thread-2 has put data :619601201
A from Thread-1 get data :619601201
B from Thread-0 get data :619601201
A from Thread-2 get data :619601201
B from Thread-1 get data :619601201
B from Thread-2 get data :619601201

楼主的情况有可能是这样的,主线程运行for(int i=0;i<2;i++)循环,然后创建了第一个线程,第一个线程运行到data = new Random().nextInt();这句之后释放了执行权,主线程拿到执行权后,又开启了第二个线程也运行到data = new Random().nextInt();将data重新赋值了一次,然后又释放了执行权,第一个线程拿到了执行权后输出了data,随便第二个线程也拿到了执行权也输出了data所以两个线程的输出结果是相同的,个人理解,不知道对不对。
作者: 王宝康    时间: 2012-8-3 22:47
本帖最后由 王宝康 于 2012-8-3 22:48 编辑

你的data是用static修饰的,是静态变量,静态变量在内存中只有一份,你的for循环里的两个线程生成的随机数可能一样,也可能不一样,因为是随机的嘛,可是,你data中的数据是你开启的线程中后运行的那个线程生成的随机数,因为静态变量在内存中只有一份,静态变量可以通过类访问,也可以通过对象访问,当通过不同的对象访问时,访问的都是内存中那个唯一的值,看下我的代码
package cn.study.staticdemo;

class Person{
        private int age ;
        static String country ;
        public Person(int age) {
                super();
                this.age = age;
        }
        public int getAge() {
                return age;
        }
        public void setAge(int age) {
                this.age = age;
        }
        public static String getCountry() {
                return country;
        }
        public static void setCountry(String country) {
                Person1.country = country;
        }
}



public class StaticDemo {

        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                Person p = new Person1(20);
                p.setCountry("北京");
                Person p1 = new Person1(23);
                p1.setCountry("上海");
                System.out.println("p的年龄是:"+p.getAge()+",p的地址是:"+p.getCountry());
                System.out.println("p1的年龄是:"+p1.getAge()+",p1的地址是:"+p1.getCountry());

        }

}

未命名.JPG (14.89 KB, 下载次数: 38)

运行截图

运行截图





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2