package volatiletest;
public class singleTest {
/* 使用volatile关键字,volatile的作用,告诉jvm该变量是容易改变的(多个线程可能修改此状态),
使用这个变量的时候,需要从内存中重新读取,修改后要马上对内存中的该变量进行更新。
因为线程之间的联系是经过内存联系起来的。
例如:
A、B两个线程共享一个变量 interest。
第1种情况(不使用volatile):A/B线程用到interest的时候,会从主存中读取出来或者缓存中(自己的内存空间,
由于没有加volatile关键字所以这个地方是随机的,除非第一次使用该变量是从主存中读取),
然后放到【自己】的内存中(每个线程都有自己的内存空间),
然后对自己内存中的变量进行修改,如果没有加volatile关键字修饰的话,
该线程对主存中的变量修改后的更新是随机的。
所以多个线程使用同一个变量的时候,尽量加上volatile,还是要加锁的地方就要加锁,volatile不能替代锁
【注】 但是大部分还是修改后马上更新
第2中情况(使用volatile): A/B线程用到interest的时候,会从主存中读取出来(绝对是主存中而不是自己的内存空间),
然后放到【自己】的内存中(每个线程都有自己的内存空间),
然后对自己内存中的变量进行修改,修改后马上将主存中的该变量进行更新
所以多个线程使用同一个变量的时候,尽量加上volatile,还是要加锁的地方就要加锁,volatile不能替代锁
因为使用加锁的同时对该变量加上volatile关键字,程序更安全。
*/
private volatile static singleTest interest=null;
private singleTest(){}
public static singleTest getInsert(){
if(interest==null){
synchronized(singleTest.class){
if(interest==null){
interest = new singleTest();
}
}
}
return interest;
}
}
package volatiletest;
public class mainTest {
public static void main(String[] args) {
// 创建10000个线程的第一种方法
RunTest[] rt = new RunTest[10000];
for(int i=0;i<10000;i++){
rt[i] = new RunTest();
rt[i].start();
}
for(int i=0;i<RunTest.arrlist.size();i++){
if(!RunTest.str.equals(RunTest.arrlist.get(i))){
System.out.println(RunTest.str+"当前线程:"+i);
System.out.println(RunTest.arrlist.get(i));
}
}
// 让主线程休眠500毫秒的,是因为其他线程还没有执行完就执行到了RunTest.count,就会出现不正确的结果(实际上是正确的)
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(RunTest.arrlist.size()); // 集合中地址的个数
System.out.println(rt.length); // 创建线程的个数
System.out.println(RunTest.count); // run方法执行的次数,也就是多个线程执行了run方法
System.out.println(RunTest.str); // 创建的对象的地址
// 使用线程池创建一千个线程的第二种方法,好处: 能判断所有线程是否全部执行完毕
/* ExecutorService exe = Executors.newFixedThreadPool(10000);
for (int i = 0; i < 10000; i++) {
exe.execute(new RunTest());
}
exe.shutdown();
while (true) {
if (exe.isTerminated()) {
for(int i=0;i<RunTest.arrlist.size();i++){
if(!RunTest.str.equals(RunTest.arrlist.get(i))){
System.out.println(RunTest.str+"当前线程:"+i);
System.out.println(RunTest.arrlist.get(i));
}else{
System.out.println("完美的单例模式");
}
}
System.out.println(""+RunTest.arrlist.size());
break;
}
}*/
}
}
package volatiletest;
import java.util.ArrayList;
public class RunTest extends Thread{
public volatile static ArrayList<String> arrlist = new ArrayList<String>();
public static String str = "";
public volatile static int count=0;
@Override
public void run() {
singleTest s = singleTest.getInsert();
synchronized(RunTest.class){
if(count==0) str = s.toString(); // 拿到第一次创建的对象
arrlist.add(s.toString());
count++;
}
}
}