JAVA 单例模式实验(头歌)

第1关:单例模式

任务描述

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

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

实现要点

在类中添加一个私有静态成员变量用于保存单例实例。

声明一个公有静态构建方法用于获取单例实例。

在静态方法中实现"延迟初始化"。 该方法会在首次被调用时创建一个新对象, 并将其存储在静态成员变量中。 此后该方法每次被调用时都返回该实例。

将类的构造函数设为私有。 类的静态方法仍能调用构造函数, 但是其他对象不能调用。

检查客户端代码, 将对单例的构造函数的调用替换为对其静态构建方法的调用。

编程要求

本任务有三个文件"Login.java"、"Client.java"和"Singleton.java",在右侧编辑器 Begin-End 内补充 Singleton 中代码,其它文件请阅读代码。

话不多说,直接上代码

Singleton.java
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
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
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()+"个用户登录");
    }
}
相关推荐
开开心心就好1 天前
内存清理软件灵活设置,自动阈值快捷键清
运维·服务器·windows·pdf·harmonyos·risc-v·1024程序员节
学传打活3 天前
【边打字.边学昆仑正义文化】_5_宇宙物种创造简史(1)
微信公众平台·1024程序员节·汉字·昆伦正义文化
xcLeigh4 天前
打破机房围墙:VMware+cpolar构建跨网络虚拟实验室
vmware·内网穿透·cpolar·实验室·远程访问·1024程序员节
开开心心就好5 天前
免费轻量电子书阅读器,多系统记笔记听书
linux·运维·服务器·安全·ddos·可信计算技术·1024程序员节
unable code6 天前
流量包取证-大流量分析
网络安全·ctf·misc·1024程序员节·流量包取证
开开心心就好6 天前
实用PDF擦除隐藏信息工具,空白处理需留意
运维·服务器·windows·pdf·迭代器模式·桥接模式·1024程序员节
unable code7 天前
浏览器取证-[GKCTF 2021]FireFox Forensics
网络安全·ctf·misc·1024程序员节·浏览器取证
unable code7 天前
内存取证-[安洵杯 2019]Attack
网络安全·ctf·misc·1024程序员节·内存取证
unable code8 天前
CTF-SPCS-Forensics
网络安全·ctf·misc·1024程序员节·取证