j2ee建立在线聊天室详细教程(第七天聊天室核心代码ChatMassage)

472 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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,为核心聊天业务工具类,代码中定义变量依次为聊天信息对象本身,用户列表,最大聊天室人数,聊天室人数(现在在线的人数),聊天信息列表,当前聊天信息总数目,以及最后,用户使用的颜色。\

单例加同步锁技术

这边我们使用的是单例模式+同步锁技术,这个就是典型的懒加载模式,可能会引发线程上的同步问题,但概率很低,效率很高,懒加载最大优点是避免资源浪费
这段代码最重要的地方之后还需要返回到聊天信息,即聊天对象 image.png

用户登录添加

接下来到了另一个板块,用户登录添加,这边使用了synchronized锁,有效避免了同一个数据对象【即用户列表对象】被多个线程同时访问,相当于是对资源加锁,表示只对这个区块的资源实行互斥访问

synchronized锁

  • 原子性所谓原子性就是指一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。synchronized修饰的类或对象的所有操作都是原子的,因为在执行操作之前必须先获得类或对象的锁,直到执行完才能释放。
  • 可见性:**可见性是指多个线程访问一个资源时,该资源的状态、值信息等对于其他线程都是可见的。 **synchronized和volatile都具有可见性,其中synchronized对一个类或对象加锁时,一个线程如果要访问该类或对象必须先获得它的锁,而这个锁的状态对于其他任何线程都是可见的,并且在释放锁之前会将对变量的修改刷新到共享内存当中,保证资源变量的可见性。
  • 有序性有序性值程序执行的顺序按照代码先后执行。  synchronized和volatile都具有有序性,Java允许编译器和处理器对指令进行重排,但是指令重排并不会影响单线程的顺序,它影响的是多线程并发执行的顺序性。synchronized保证了每个时刻都只有一个线程访问同步代码块,也就确定了线程执行同步代码块是分先后顺序的,保证了有序性。 在添加用户之前,我们需要做一个判断,判断条件为:是否存在此用户,并且还需要判定我们聊天室的人数是否满员,判断是否满员的代码如下:

image.png
在条件判断完之后,就走到下一步,添加新用户,然后还需要添加用户聊天时字的颜色,这边添加颜色时,和用户名相关联,以K:V方式存储

K:V方式存储

键值存储,即Key-Value存储,简称KV存储。它是NoSQL存储的一种方式。它的数据按照键值对的形式进行组织,索引和存储。KV存储非常适合不涉及过多数据关系业务关系的业务数据,同时能有效减少读写磁盘的次数,比SQL数据库存储拥有更好的读写性能。

颜色生成

颜色的生成由以下代码进行,随机创建颜色,之后返回16进制的随机颜色值

image.png

检测用户名是否重复

最后解释一段代码,也就是用户名字是否重复
这边用的是暴力遍历,最为简单

image.png