版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35974759/article/details/89489694
title: 对象及变量的并发访问
categories: Java多线程编程核心技术
tags: 多线程
time: 2019-04-24 11:44:32
立即加载/饿汉模式
立即加载就是在使用类之前已经将对象创建完毕,常见的实现方法就是new实例化。
public class MyThread {
private static MyThread INSTANCE = new MyThread();
private MyThread() {}
public static MyThread getInstance() {
return INSTANCE;
}
}
class Test {
public static void main(String[] args) {
ThreadA a = new ThreadA(MyThread.getInstance());
a.start();
ThreadA b = new ThreadA(MyThread.getInstance());
b.start();
ThreadA c = new ThreadA(MyThread.getInstance());
c.start();
}
}
class ThreadA extends Thread {
private MyThread myThread;
public ThreadA(MyThread myThread) {
this.myThread = myThread;
}
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName() +" " + myThread.hashCode());
}
}
class ThreadB extends Thread {
private MyThread myThread;
public ThreadB(MyThread myThread) {
this.myThread = myThread;
}
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName() +" " + myThread.hashCode());
}
}
class ThreadC extends Thread {
private MyThread myThread;
public ThreadC(MyThread myThread) {
this.myThread = myThread;
}
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName() +" " + myThread.hashCode());
}
}
运行结果:
Thread-0 1315983110
Thread-2 1315983110
Thread-1 1315983110
3个线程运行后得到相同的一个hashcode值,说明对象是同一个,也就实现了立即加载型单例设计模式
立即加载,缺点是不能有其他实例变量,因为getInstance方法没有同步,所以有可能会出现线程不安全问题。
延迟加载/懒汉模式
延迟加载就是在执行get方法后才会去创建对象,常见的方式就是在调用get方法后用new实例化。
public class MyThread1 {
private static MyThread1 instance;
private MyThread1(){}
synchronized public static MyThread1 getInstance() {
if (instance == null) {
instance = new MyThread1();
}
return instance;
}
}
class Test2 {
public static void main(String[] args) {
ThreadE e = new ThreadE(MyThread.getInstance());
e.start();
ThreadD d = new ThreadD(MyThread.getInstance());
d.start();
}
}
class ThreadE extends Thread {
private MyThread myThread;
public ThreadE(MyThread myThread) {
this.myThread = myThread;
}
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName() +" " + myThread.hashCode());
}
}
class ThreadD extends Thread {
private MyThread myThread;
public ThreadD(MyThread myThread) {
this.myThread = myThread;
}
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName() +" " + myThread.hashCode());
}
}
运行结果:
Thread-0 985847520
Thread-1 985847520
使用的是同步方法的方式,效率比较低下,可以用同步代码块进行优化
public static MyThread1 getInstance() {
if (instance == null) {
synchronized (MyThread1.class) {
instance = new MyThread1();
}
}
return instance;
}
但是在多线程中仍然无法解决得到同一个实例对象的结果。
解决方式:使用DCL双重锁检查机制
使用DCL双检查锁机制
public class MyThread3 {
private static MyThread3 instance;
private MyThread3(){}
public static MyThread3 getInstance() {
if (instance == null) {
synchronized (MyThread1.class) {
if (instance == null) {
instance = new MyThread3();
}
}
}
return instance;
}
}
class Test3 {
public static void main(String[] args) {
ThreadF e = new ThreadF(MyThread3.getInstance());
e.start();
ThreadG d = new ThreadG(MyThread3.getInstance());
d.start();
}
}
class ThreadF extends Thread {
private MyThread3 myThread;
public ThreadF(MyThread3 myThread) {
this.myThread = myThread;
}
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName() +" " + myThread.hashCode());
}
}
class ThreadG extends Thread {
private MyThread3 myThread;
public ThreadG(MyThread3 myThread) {
this.myThread = myThread;
}
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName() +" " + myThread.hashCode());
}
}
执行结果:
Thread-0 1211216510
Thread-1 1211216510
DCL很好的解决了懒汉式加载过程中多线程非线程安全的问题,DCL也是大多数多线程结合单例模式使用的解决方案。
静态内置类实现单例模式
public class MyThread4{
private MyThread4(){}
private static class MyThread3Holder {
private static MyThread4 instance = new MyThread4();
}
public static MyThread4 getInstance() {
return MyThread3Holder.instance;
}
}
class Test4 {
public static void main(String[] args) {
ThreadH h = new ThreadH();
ThreadI i = new ThreadI();
h.start();
i.start();
}
}
class ThreadH extends Thread {
@Override
public void run() {
super.run();
System.out.println(MyThread4.getInstance().hashCode());
}
}
class ThreadI extends Thread {
@Override
public void run() {
super.run();
System.out.println(MyThread4.getInstance().hashCode());
}
}
运行结果:
726367991
726367991
序列化和反序列化单例模式实现
static 代码块实现单例模式
public class MyThread5 {
private static MyThread5 instance;
private MyThread5(){}
static {
instance = new MyThread5();
}
public static MyThread5 getInstance() {
return instance;
}
}
class Test5 {
public static void main(String[] args) {
ThreadM m = new ThreadM();
ThreadN n = new ThreadN();
m.start();
n.start();
}
}
class ThreadM extends Thread {
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName() + " :" + MyThread5.getInstance().hashCode());
}
}
class ThreadN extends Thread {
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName() + " :" + MyThread5.getInstance().hashCode());
}
}
运行结果:
Thread-1 :726367991
Thread-0 :726367991