没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
一、单例设计模式的线程安全问题
(1)饿汉式没有线程安全问题
(2)懒汉式线程安全问题
1、案例
2、方式1-同步方法
3、方式2-同步代码块
4、优化
二、代码
(1)实现线程安全的懒汉式
(2)使用内部类
一、单例设计模式的线程安全问题
单例设计模式博客链接:https://blog.csdn.net/m0_55746113/article/details/134492961
饿汉式:不存在线程安全问题。
懒汉式:存在线程安全问题,(需要使用 同步机制 来处理)
(1)饿汉式没有线程安全问题
饿汉式 :在类初始化时就直接创建单例对象,而类初始化过程是没有线程安全问题的。
🍰
格式
【举例】
形式一:
class Singleton {
// 1.私有化构造器
private Singleton() {
}
// 2.内部提供一个当前类的实例
// 4.此实例也必须静态化
private static Singleton single = new Singleton();
// 3.提供公共的静态的方法,返回当前类的对象
public static Singleton getInstance() {
return single;
}
}
形式二:
测试类:
package com.atguigu.single.hungry;
public class HungrySingle {
private static HungrySingle INSTANCE = new HungrySingle(); //对象是否声明为
final 都可以
private HungrySingle(){}
public static HungrySingle getInstance(){
return INSTANCE;
}
}
/*
public class HungryOne{
public static final HungryOne INSTANCE = new HungryOne();
private HungryOne(){}
}*/
public enum HungryOne{
INSTANCE
}
package com.atguigu.single.hungry;
public class HungrySingleTest {
static HungrySingle hs1 = null;
static HungrySingle hs2 = null;
//演示存在的线程安全问题
public static void main(String[] args) {
Thread t1 = new Thread() {
@Override
public void run() {
hs1 = HungrySingle.getInstance();
}
};
Thread t2 = new Thread() {
@Override
public void run() {
hs2 = HungrySingle.getInstance();
}
};
(2)懒汉式线程安全问题
懒汉式 :延迟创建对象,第一次调用getInstance方法再创建对象。
🍰
格式
1、案例
【案例】
举个例子:
t1.start();
t2.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(hs1);
System.out.println(hs2);
System.out.println(hs1 == hs2);//true
}
}
class Singleton {
// 1.私有化构造器
private Singleton() {
}
// 2.内部提供一个当前类的实例
// 4.此实例也必须静态化
private static Singleton single;
// 3.提供公共的静态的方法,返回当前类的对象
public static Singleton getInstance() {
if(single == null) {
single = new Singleton();
}
return single;
}
}
public class BankTest {
线程安全问题:若有两个线程去调用 getInstance 方法,他们主要的目的是为了获取 instance 实
例,这个实例就相当于是“共享数据”。
}
class Bank {
//私有化构造器
private Bank() { //这里不提供实例变量了
}
//先不造好,通过一个方法返回
private static Bank instance = null;
public static Bank getInstance() {
if (instance == null) {
instance = new Bank();
}
return instance;
}
}
若第一个线程判断if,发现是null,就进去了。假设此时被 sleep 阻塞了,然后Bank实例并没有被
创建成功。
此时第二个线程也进入了if,判断一下发现是null,然后将Bank实例创建好了。
现在第一个线程阻塞结束,就会再创建一个Bank实例。
所以, instance = new Bank(); 语句被先后执行了两次,这显然就不是我们想看到的。
🗳
将刚才的问题用代码描述出来。
将b1与b2设置为静态的,就可以直接在 main 方法中去调用他们了。
在static方法内部只能访问类的static修饰的属性和方法,不能访问类的非static结构。
现在提供两个线程,让他们去调用 getInstance 方法。
就整一个匿名子类的对象吧:
在 run 方法里面,通过 Bank 调用 getInstance 方法,如下:
public class BankTest {
static Bank b1=null; //为了在main方法中调用的时候,不使用对象来调用(方便一点),这
里就设置成静态的
static Bank b2=null;
public static void main(String[] args) {
}
}
Thread t1=new Thread(){
//重写
};
public class BankTest {
static Bank b1=null; //为了在main方法中调用的时候,不使用对象来调用(方便一点),这
里就设置成静态的
static Bank b2=null;
public static void main(String[] args) {
Thread t1=new Thread(){
@Override
public void run() {
b1=Bank.getInstance(); //将方法返回的对象赋给b1
}
};
t1.start();
}
}
剩余27页未读,继续阅读
资源评论
雨翼轻尘
- 粉丝: 6w+
- 资源: 130
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功