目录
先说结论
成员变量
1.成员变量---int类型的成员变量number 线程共享,会有并发
2.成员变量---string类型 线程共享,会有并发
3.成员变量---int /string类型的数组 线程共享,会有并发
4.成员变量---ArrayList 线程共享,会有并发
5.成员变量---HashMap 线程共享,会有并发
局部变量
1.局部变量-- int类型 线程不共享,不会有并发
2.局部变量---string类型 线程不共享,不存在并发
3.局部变量-- int类型的数组 线程不共享,不存在并发
4.局部变量---ArrayList 线程不共享,不存在并发
5.局部变量---HashMap 线程不共享,不存在并发
作为成员变量,线程共享存在并发的有
1.int类型
2.string类型
3.int[] /string[]数组
4.ArrayList
5.HashMap
作为局部变量,线程不共享没有并发的有
1.int类型
2.string类型
3.int[] /string[]数组
4.ArrayList
5.HashMap
前提条件,把这个类设成是单例模式,也就是说,这个类只能创建一个对象,然后多个线程在一个对象中去争抢资源.
public class Stu {
private int number;
private String age;
private String math;
private int[] shuzu= {1,2,3} ;
public void aa(){
number++;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(number);
}
@Component
public class MyRunnable implements Runnable{
@Override
public void run(){
//创建出stu的单例对象
Stu stu = Stu.getInstance();
stu.aa();
//把stu对象的地址打印出来
System.out.println(Thread.currentThread().getName()+" 嘿嘿 "+System.identityHashCode(stu));
}
}
public class testb {
public static void main(String[] args) {
//创建线程池
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
pool.submit(new MyRunnable());
}
pool.shutdown();
}
}
创建10个线程去执行stu对象的成员变量的number++;
下图是结果:
打印的int类型的成员变量的内存地址都一样.这是为什么?
打印的结果混乱,证明多线程争抢,发生了并发.
创建10个线程去获得单例对象stu内的成员变量string name, 让10个线程都去改变string name的值,然后打印最后string name的值,和每个线程执行到的string name的内存
结果显示,10个线程去改变值后的string name的内存是值相同的内存一样,值不相同的内存不一样.
结果是混乱的,证明有并发的现象出现,就是发生了并发.
创建10个线程去获得单例对象stu内的成员变量int[] shuzu, 让10个线程都去对数组减一操作,然后打印最后数组的元素的值,和每个线程执行到的数组的内存
下面是结果:
结果显示,10个线程创建的数组的内存都是一样的,证明这个成员变量的数组是线程共享的,一个线程new出来一个数组后,那么其他数组就共享使用这个数组了.
而每个线程都去减一后,打印的结果很乱有重复,证明有并发的现象出现,就是发生了并发.
创建10个线程去获得单例对象stu内的成员变量ArrayList
下面是结果:
结果显示,10个线程创建的ArrayList集合的内存都是一样的,证明这个成员变量的集合是线程共享的,一个线程new出来一个集合后,那么其他数组就共享使用这个集合了.
而每个线程都去对集合添加1元素后,打印的结果有null出现,证明有并发的现象出现,就是发生了并发.
创建10个线程去获得单例对象stu内的成员变量hashmap
下面是结果:
结果显示,10个线程创建的hashmap
而每个线程都去对集合hashmap添加一个键值对,打印的结果最后是第3个线程的,证明有并发的现象出现,就是发生了并发.
创建10个线程去执行stu对象的aa()方法里的局部变量的number++;
下图是结果:
内存地址都是一样的?
结果都是1.证明不存在并发
创建10个线程去执行stu对象的aa()方法里的string name +"啊";
结果内存都不一样,证明局部变量sting类型线程不共享.
结果值都是一样的,证明线程没有发生争抢.
创建10个线程去执行单例对象stu的aa()方法, 让这10个数组都去对这个数组减一操作,然后打印最后数组的元素的值,和每个线程执行到的数组的内存
下图是结果
结果证实:每个线程new出的数组的内存地址都不一样... (int [] arr=new int[]{0})这种在成员方法里的局部变量, 每个线程都会自己去new一个数组出来, 会在堆中new出10个地址不同的数组来,然后每个线程执行的时候各找各的new出的数组,所以它们互不影响.
结果证实:每个线程都new了一个自己的数组,因此它们各自减一,得的结果都是9,不存在并发.
所以, 数组作为局部变量,是线程不共享的,是线程安全的.
创建10个线程去new局部变量ArrayList
下面是结果:
结果显示,10个线程创建的ArrayList集合的内存是不一样的,证明这个局部变量的集合是线程私有的.
而每个线程都去对集合添加1元素后,打印的结果都为1,证明不存在并发.
创建10个线程去new局部变量hashmap
下面是结果:
结果显示,10个线程创建的hashmap
而每个线程都去对hashmap添加一个键值对后,打印的结果互不影响,证明不存在并发.