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()+"个用户登录");
    }
}
相关推荐
西电研梦8 小时前
考研倒计时30天丨和西电一起向前!再向前!
人工智能·考研·1024程序员节·西电·西安电子科技大学
惜.己9 小时前
Jmeter中的断言(四)
测试工具·jmeter·1024程序员节
·云扬·16 小时前
Java IO 与 BIO、NIO、AIO 详解
java·开发语言·笔记·学习·nio·1024程序员节
网安_秋刀鱼20 小时前
PHP代码审计 --MVC模型开发框架&rce示例
开发语言·web安全·网络安全·php·mvc·1024程序员节
HUODUNYUN1 天前
小程序免备案:快速部署与优化的全攻略
服务器·网络·web安全·小程序·1024程序员节
惜.己1 天前
Jmeter的后置处理器(二)
测试工具·github·1024程序员节
惜.己2 天前
Jmeter中的断言(一)
测试工具·jmeter·1024程序员节
cainiao0806052 天前
《物理学进展》
1024程序员节·核心期刊·知网期刊·职称评审
FFDUST2 天前
C++ —— string类(上)
c语言·开发语言·数据结构·c++·stl·1024程序员节
惜.己2 天前
Jmeter中的断言(三)
测试工具·jmeter·1024程序员节