0基础学java之Day29(单例模式、死锁)

单例模式

理解:在整个项目中,该类的实例只能有一个

1.饿汉式

  • 优点:线程安全

  • 缺点:浪费资源

复制代码
public class A {
​
    private static A a = new A();
    
    private A(){}
    
    public static A getInstance(){
        return a;
    }
    
    public static void method(){
        System.out.println("好好学习,天天向上");
    }
​
    
public static void main(String[] args) {
        
//      A a1 = A.getInstance();
//      A a2 = A.getInstance();
//      
//      System.out.println(a1 == a2);//true
        
        A.method();//哪怕调用方法也会创建对象开辟空间
    }

2.饱汉式

  • 优点:节约资源

  • 缺点:线程不安全

复制代码
public class A {
​
    private static A a;
    
    private A(){}
    
    public static A getInstance(){
        if(a == null){
            a = new A();
        }
        return a;
    }
    
    public static void method(){
        System.out.println("好好学习,天天向上");
    }
}
​
​
public static void main(String[] args) {
        
        A a1 = A.getInstance();
        A a2 = A.getInstance();
        System.out.println(a1 == a2);//true
        
//      A.method();
    }

3.双重校验

  • 优点:节约资源、线程安全
复制代码
public class A {
    
    //创建一个对象的步骤:A a = new A();
    //1.创建对象空间,分配地址 -- new --> 0x001
    //2.调用构造方法,初始化成员变量
    //3.将对象地址赋值给引用
    //注意:创建对象的步骤有可能是1、2、3,也有可能是1、3、2
    //注意:使用volatile修饰的对象被创建的步骤必须是1、2、3
​
    private static volatile A a;
    
    private A(){}
    
    public static A getInstance(){
        
        if(a == null){
            synchronized (A.class) {
                if(a == null){
                    a = new A();
                }
            }
        }
        return a;
    }
    
    public static void method(){
        System.out.println("好好学习,天天向上");
    }
​
    
public static void main(String[] args) {
        
        A a1 = A.getInstance();
        A a2 = A.getInstance();
        
        System.out.println(a1 == a2);//true
        
//      A.method();
    }    

死锁

  • 注意:死锁不一定每次都出现

  • 经验:尽可能避免锁嵌套

复制代码
public class Test01 {
​
    public static void main(String[] args) {
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (KuaiZi.a) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (KuaiZi.b) {
                        System.out.println("哲学家1发现了");
                    }
                }
            }
        }).start();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (KuaiZi.b) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (KuaiZi.a) {
                        System.out.println("哲学家2发现了");
                    }
                }
            }
        }).start();
        
        
    }
}
class KuaiZi{
    
    public static Object a = new Object();
    public static Object b = new Object();
    
}
相关推荐
、BeYourself4 分钟前
Spring AI 文档切片策略优化指南
java·人工智能·spring
xuxie996 分钟前
【无标题】
java·开发语言
堕2747 分钟前
java数据结构当中的《Lambda表达式》
java·数据结构·python
摇滚侠9 分钟前
基于 session 的登录认证方式,基于 token 的登录认证方式,对比
java·开发语言·intellij-idea
北国1379 分钟前
【Java】多线程输出滞后/错误解决&&线程创建方式与原理
java·开发语言
假客套10 分钟前
2026 JAVA 腾讯云人脸比对工具类,支持url或者base64进行比对
java·spring boot·腾讯云人脸比对
wfsm11 分钟前
reactive streaming
java
Coder_Boy_14 分钟前
【Java核心】JVM核心知识清单
java·开发语言·jvm
在坚持一下我可没意见18 分钟前
ideaPool论坛系统测试报告
java·spring boot·功能测试·selenium·jmeter·mybatis·压力测试
像少年啦飞驰点、25 分钟前
零基础入门 RabbitMQ:从消息队列是什么到 Spring Boot 实战收发消息
java·spring boot·微服务·消息队列·rabbitmq·异步编程