持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第十七天,点击查看活动详情
-------20220621
今天的内容,真的超级超级干货!!!算是我们聊天室的核心吧,也不知道今天能不能讲的完,讲不完的话,就今天先发,然后明天再来补全!今天要给大家介绍的是我们Bean里面ChatMassage.java,看起来他只有简简单单的100多行代码,其实真的是我们聊天室的核心代码
ChatMassage.java
实现步骤
核心业务bean------->ChatMassage
单例模式
- 同步锁技术
单例模式下的同步锁,叫懒汉模式加双重检查锁
聊天数据封装 - 聊天记录
- 聊天记录数 用户数据封装
- 用户名
- 用户数
- 用户颜色 聊天室本身数据封装:
- 满员人数
- 当前人数
- 判断是否满员
- 已有用户获取
- 进入,添加用户
- 获取聊天数据
- 退出
代码文件
package bean;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
/**
* @author zzl
*
*/
public class ChatMassage {
public static ChatMassage chatMassage = null;
private List<String> users = new ArrayList<String>();
private final int USER_NUMBER = 50;
public static int userNum = 0;
private List<String> massages = new ArrayList<String>();
public static int mass_num = 0;
private Map<String, String> color = new HashMap<String, String>();
protected ChatMassage() {
}
public static ChatMassage Instance() {
if (chatMassage == null) {
return chatMassage = new ChatMassage();
}
return chatMassage;
}
public boolean addUser(String name) {
synchronized (users) {
if (!this.hasUser(name) && !isFull()) {
users.add(name);
String color = createColor();
this.color.put(name, color);
userNum++;
return true;
}
}
return false;
}
public boolean isFull() {
if (userNum < this.USER_NUMBER) {
return false;
}
return true;
}
public boolean hasUser(String name) {
for (String na : users) {
if (name.equalsIgnoreCase(na)) {
return true;
}
}
return false;
}
public String getUsers() {
StringBuffer user = new StringBuffer();
int i = 0;
while (i < userNum) {
String name = this.users.get(i);
String color = this.getColor(name);
String userMass = "<font color='" + color + "'>" + name + "</font><br>";
user.append(userMass);
i++;
}
return user.toString();
}
public String getMassage(int i) {
StringBuffer massage = new StringBuffer();
while (i < mass_num && i >= 0) {
massage.append(massages.get(i));
i++;
}
return massage.toString();
}
public void setMassage(String massage) {
synchronized (massages) {
massages.add(massage);
mass_num++;
}
}
public void exit(String name) {
if (users.remove(name)) {
userNum--;
if (userNum == 0) {
mass_num = 0;
massages.clear();
users.clear();
color.clear();
} else {
color.remove(name);
}
}
}
public String getColor(String username) {
return color.get(username);
}
private String createColor() {
StringBuffer color = new StringBuffer("#");
Random random = new Random();
for (int i = 0; i < 3; i++) {
int a = random.nextInt(256); // 0-255
color.append(Integer.toHexString(a));
}
return color.toString();
}
}
----------20220622
昨天写到这边就休息了,那今天补上
代码解释
这次的代码chatMassage.java,为核心聊天业务工具类,代码中定义变量依次为聊天信息对象本身,用户列表,最大聊天室人数,聊天室人数(现在在线的人数),聊天信息列表,当前聊天信息总数目,以及最后,用户使用的颜色。\
单例加同步锁技术
这边我们使用的是单例模式+同步锁技术,这个就是典型的懒加载模式,可能会引发线程上的同步问题,但概率很低,效率很高,懒加载最大优点是避免资源浪费
这段代码最重要的地方之后还需要返回到聊天信息,即聊天对象
用户登录添加
接下来到了另一个板块,用户登录添加,这边使用了synchronized锁,有效避免了同一个数据对象【即用户列表对象】被多个线程同时访问,相当于是对资源加锁,表示只对这个区块的资源实行互斥访问
synchronized锁
- 原子性:所谓原子性就是指一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 被
synchronized修饰的类或对象的所有操作都是原子的,因为在执行操作之前必须先获得类或对象的锁,直到执行完才能释放。 - 可见性:**可见性是指多个线程访问一个资源时,该资源的状态、值信息等对于其他线程都是可见的。 **synchronized和volatile都具有可见性,其中synchronized对一个类或对象加锁时,一个线程如果要访问该类或对象必须先获得它的锁,而这个锁的状态对于其他任何线程都是可见的,并且在释放锁之前会将对变量的修改刷新到共享内存当中,保证资源变量的可见性。
- 有序性:有序性值程序执行的顺序按照代码先后执行。 synchronized和volatile都具有有序性,Java允许编译器和处理器对指令进行重排,但是指令重排并不会影响单线程的顺序,它影响的是多线程并发执行的顺序性。synchronized保证了每个时刻都只有一个线程访问同步代码块,也就确定了线程执行同步代码块是分先后顺序的,保证了有序性。 在添加用户之前,我们需要做一个判断,判断条件为:是否存在此用户,并且还需要判定我们聊天室的人数是否满员,判断是否满员的代码如下:
在条件判断完之后,就走到下一步,添加新用户,然后还需要添加用户聊天时字的颜色,这边添加颜色时,和用户名相关联,以K:V方式存储
K:V方式存储
键值存储,即Key-Value存储,简称KV存储。它是NoSQL存储的一种方式。它的数据按照键值对的形式进行组织,索引和存储。KV存储非常适合不涉及过多数据关系业务关系的业务数据,同时能有效减少读写磁盘的次数,比SQL数据库存储拥有更好的读写性能。
颜色生成
颜色的生成由以下代码进行,随机创建颜色,之后返回16进制的随机颜色值
检测用户名是否重复
最后解释一段代码,也就是用户名字是否重复
这边用的是暴力遍历,最为简单