当前位置: 首页 > article >正文

JAVA 单例模式实验(头歌)

第1关:单例模式

任务描述
在企业网站后台系统中,一般会将网站统计单元进行独立设计,比如登录人数的统计、IP 数量的计数等。在这类需要完成全局统计的过程中,就会用到单例模式,即整个系统只需要拥有一个计数的全局对象。

本关任务:模拟网站登录,高并发场景。模拟 10 个登录线程,程序输出登录总数。

实现要点
在类中添加一个私有静态成员变量用于保存单例实例。
声明一个公有静态构建方法用于获取单例实例。
在静态方法中实现"延迟初始化"。 该方法会在首次被调用时创建一个新对象, 并将其存储在静态成员变量中。 此后该方法每次被调用时都返回该实例。
将类的构造函数设为私有。 类的静态方法仍能调用构造函数, 但是其他对象不能调用。
检查客户端代码, 将对单例的构造函数的调用替换为对其静态构建方法的调用。
编程要求
本任务有三个文件“Login.java”、“Client.java”和“Singleton.java”,在右侧编辑器 Begin-End 内补充 Singleton 中代码,其它文件请阅读代码。

话不多说,直接上代码

Singleton.java
package step1;

import java.util.concurrent.atomic.AtomicLong;

public class Singleton {
    private static Singleton instance;
    //AtomicLong是以原子方式操作long值的类,作用是保证并发时线程安全的累加
    private AtomicLong count = new AtomicLong(0);
    /********** Begin *********/
    //此处增加Singleton的构造函数
   private Singleton() {  
            }
    /********** End *********/
    public static Singleton GetInstance(){
        /********** Begin *********/
        //考虑线程安全问题
        if (instance == null) {  
            synchronized (Singleton.class) {  
                if (instance == null) {  
                    instance = new Singleton();  
                }  
            }  
        }  
        return instance;  
    }
         /********** End *********/
    public AtomicLong getCount() {
        return count;
    }
    public void setCount() {
        count.addAndGet(1);
    }
}
Login.java
package step1;
//Runnable 接口由其实现类来由线程执行对应的实例。对于实现类必须是实现方法 run
public class Login implements Runnable{
    private String loginname;
    public String getLoginname() {
        return loginname;
    }
    public void setLoginname(String loginname) {
        this.loginname = loginname;
    }
    @Override
    public void run() {
        Singleton lazySingleton =Singleton.GetInstance();
        lazySingleton.setCount();
        /*调试时观察
        System.out.println(getLoginname()+"登录成功."+lazySingleton);
        */
    }
}
Client.java
package step1;

public class Client {
    public final static int num = 10;

    public static void main(String[] args) throws InterruptedException {
        
        ///创建10个线程,模拟10个用户登录
        Thread[] threads = new Thread[num];
        for (int i = 0; i < num; i++) {
            Login login = new Login();
            login.setLoginname("" + String.format("%2s", (i + 1)) + "号用户");
            //创建了线程threads[i],并把login对象(已实现Runnable接口)放入线程中
            threads[i]=new Thread(login);
            //线程状态转换为RUNNABLE
            threads[i].start();
        }
        for (Thread thread : threads) {
            //Client等待线程结束之后才能继续运行,防止最后一行的System.out.println提前运行
            thread.join();
        }
        System.out.println("网站共有"+Singleton.GetInstance().getCount()+"个用户登录");
    }
}


http://www.kler.cn/news/364526.html

相关文章:

  • 人工智能算法之双倍体遗传算法(DGA)
  • 故障诊断 | CNN-GRU卷积神经网络-门控循环单元组合模型的故障诊断(Matlab)
  • ActivationType, Pool, ModelType(helpers文件中的classes.py)
  • C++11 28-纯虚函数的默认实现 The default implementation of pure virtual functions
  • 微信小程序绘制轨迹
  • APP综合应用之业务场景脚本测试任务(5)--多重继承与总结
  • 【ROS GitHub使用】
  • ​8.13TB高清卫星影像更新(WGS84坐标投影)
  • 简单三步完成 Telegram 生态的 Web3 冷启动
  • rsync算法原理
  • Vue3 + Element Plus 封装文本超出长度显示省略号,鼠标移上悬浮展示全部内容的组件
  • 关于建造者模式(Builder Pattern)
  • 写出Windows操作系统内核的程序员,70多岁,还去办公室敲代码
  • Scala trait
  • 912.排序数组(计数排序)
  • QML列表视图 ListView的使用
  • Jenkins + GitLab + Docker实现自动化部署(Java项目)
  • 深入了解 Pandas 中的数据:Series 和 DataFrame 的使用指南
  • 借助栈逆置单链表
  • 基于YOLOv8深度学习的高密度人脸智能检测与统计系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测
  • 【golang】学习文档整理
  • OpenFace安装教程及踩坑记录 (Ubuntu20.04—2024.10.24)
  • ElasticSearch全文检索和倒排索引
  • 杂项笔记
  • 100种算法【Python版】第8篇——群体智能优化算法之人工蜂群算法
  • Docker容器的基础镜像:构建现代应用程序的基石