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

dede重工蓝色企业免费网站模板怎样创造一个网站

dede重工蓝色企业免费网站模板,怎样创造一个网站,许昌网络推广公司,中国建设部官网信息查询完整版代码 java -聊天室的代码: 用于存放聊天室的项目的代码和思路导图https://gitee.com/to-uphold-justice-for-others/java---code-for-chat-rooms.git 多线程并发问题 多线程的并发问题主要出现在当一个程序涉及多个线程同时运行时#xff0c;这些线程可能会同时访问共…完整版代码  java -聊天室的代码: 用于存放聊天室的项目的代码和思路导图https://gitee.com/to-uphold-justice-for-others/java---code-for-chat-rooms.git 多线程并发问题 多线程的并发问题主要出现在当一个程序涉及多个线程同时运行时这些线程可能会同时访问共享资源如数据、内存、文件等。由于多个线程之间的竞争和冲突这可能导致程序出现不稳定、不可预测的行为。 上次我们对服务端存储的客户端的数据集合进行操作,真实情况 服务端可能面临多频繁的客户传递数据,这次我们需要考虑多线程的问题 synchronized的引用 synchronized是一个关键字用于控制多个线程对共享资源的访问以避免并发问题。  1.方法上的引入 修饰实例方法 当一个方法被synchronized修饰时该方法就被称为同步方法。这意味着一次只能有一个线程可以进入该方法。当某个线程正在执行同步方法时其他任何线程都无法访问该方法直到当前线程执行完该方法并释放锁。 public synchronized void synchronizedMethod() { // 线程安全的代码 } 修饰静态方法 当synchronized修饰一个静态方法时它锁定的是该类的Class对象。这意味着所有访问这个静态同步方法的线程都需要获得这个类的Class对象的锁这样在一个时间点只能有一个线程能够执行这个静态方法。 public static synchronized void staticSynchronizedMethod() {       // 线程安全的代码   } 2.代码块的引入 修饰代码块synchronized也可以用来修饰一个代码块允许更细粒度的控制。这允许开发者指定哪些特定的代码段需要同步而不是整个方法。在这种情况下开发者需要提供一个对象作为锁。 this 是 调用改方法的对象类 public void someMethod() {       synchronized(this) {           // 线程安全的代码       }   } 总结 : synchronized修饰方法时候整个方法相当于带了一把锁,而修饰代码块的时候就整个代码快就上了一把锁,而且修饰代码快,可以根据具体义务灵活使用,且可以根据争抢的资源进行上锁避免了并发问题出现. 这边举个例子 多个线程调用同一个类的同一个方法 这边同步锁synchronized修饰的代码块锁的是这个boo对象类,这边可以在改为sychronized(this) 注意的是sychronized(boo.class)中的boo.class获取对象的类涉及到反射的概念 public class SyncDemo3 {public static void main(String[] args) { // Boo b1 new Boo(); // Boo b2 new Boo(); // Thread t1 new Thread(()-b1.doSome()); // Thread t2 new Thread(()-b2.doSome());Thread t1 new Thread(()-Boo.doSome());Thread t2 new Thread(()-Boo.doSome());t1.start();t2.start();} }class Boo{ // public synchronized static void doSome(){public static void doSome(){//显示的获取类对象可以用:类名.class获取到synchronized (Boo.class) {//静态方法中指定同步监视器对象通常就用当前类的类对象try {Thread t Thread.currentThread();System.out.println(t.getName() :正在执行doSome方法...);Thread.sleep(5000);System.out.println(t.getName() :执行doSome方法完毕!);} catch (InterruptedException e) {}}} }回归正题 服务端 因为我们是服务端收集客户端的数据集合是对集合进行删减,所以我们使用同步锁同步块 //这边是锁添加集合元素synchronized (allOut) {allOut.add(pw);} //这边是锁删除集合元素synchronized (allOut) {allOut.remove(pw);} 同于遍历集合同时,我们服务端的集合可能在添加集合元素也可能在删除集合元素,我们需要加一把互斥锁 使用synchronized关键字实现互斥锁 synchronized是Java内置的语言特性它提供了隐式的互斥锁。当线程进入synchronized方法或代码块时它会自动获取对象的内置锁当线程退出synchronized方法或代码块时它会自动释放锁。 这边定义一个同步方法,我们知道当两个方法上锁的锁的是对象类,当我们新建一个实例化类的时候, 在调用一个方法时候其对象类会上锁,以保证另一个方法不会被调用  public class Counter { private int count 0; public synchronized void increment() { count; } public synchronized int getCount() { return count; } } 接下来我们解决如何私聊的问题,我们知道在进入聊天室之前会输入昵称 这边只有服务端根据昵称选择对应的客户端进行发送对应的信息即可, 这边先私有一个方法 这边我们使用一个正则表达式,根据 符判断其属于私聊, 截取信息方面 nickname: message 可以根据:进行拆分,这边因为只有一个:我们使用的substring进行对信息进行拆分  indexof 用于查询对应的元素的返回其所用索引值 思路 第一次if判断用户输出是否符合私聊的正则表达式,第二次if是判断用户是否存在 private void sendMessageToSomeOne(String message){/*张三-李四 发送一个私聊message:李四:在吗?对方昵称:聊天消息.:.tips:.在正则表达式里表示任意一个字符是一个量词,表示前面的内容出现1次以上所以.表示1次以上的任意字符*///进行私聊格式验证if(message.matches(.:.)){//根据聊天消息,截取出对方的昵称 abc:你好String toNickname message.substring(1, message.indexOf(:));if(allOut.contains(toNickname)) {//对方昵称在allOut中是否存在//获取对方的输出流PrintWriter pw allOut.get(toNickname);//张三悄悄对你说:在吗?String content message.substring(message.indexOf(:) 1);pw.println(nickname悄悄对你说:content);}else{PrintWriter pw allOut.get(nickname);//用户[abc]不存在pw.println(用户[toNickname]不存在);}}else{//格式不对,则同时该客户端格式不对PrintWriter pw allOut.get(nickname);pw.println(私聊格式不对,应当是对方昵称:聊天消息);}} 调用私聊的方法 因为我们服务端接受客户端发送的消息和私聊对应的用户名进行判断 while ((message br.readLine()) ! null) {//聊天信息以开始,应当是私聊if(message.startsWith()){sendMessageToSomeOne(message);}else {sendMessage(nickname [ ip ]说: message);} 问题,私聊的信息有点乱,我们集合是根据用户的输入的数据存储,并没有将昵称和输入到服务端的值绑定 解决 使用MAP 二维集合利用键值对将其昵称和数据存储 这边利用map添加元素put(index,element)方法 , remove(key) 注意这边移除是键值对,c ontainskey()判断包含元素, values()获取集合中的值 服务端 // private CollectionPrintWriter allOut new ArrayList(); private  MapString,PrintWriter allOut new HashMap();  修改点 集合 添加元素  synchronized (allOut) { // allOut.add(pw);allOut.put(nickname,pw);} 修改点 集合移除文件输出流变为移除对应的昵称 synchronized (allOut) { // allOut.remove(pw);allOut.remove(nickname);} 修改点 遍历集合 改为对应values遍历 synchronized (allOut) { // for (PrintWriter o : allOut) {//发送给所有客户端for(PrintWriter o : allOut.values()){o.println(message);}} 修改点 私聊是否包含该用户时候变为containkey if(allOut.contains(toNickname)) - if   if(allOut.containskey(toNickname)) 这边是全部代码 客户端 package socket;import java.io.*; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.Scanner;/*** 聊天室客户端*/ public class Client {/*java.net.Socket 套接字Socket封装了TCP协议的通讯细节使用它可以和远端计算机建立网络链接并基于两条流(一条输入一条输出)的读写与对方进行数据交换。*/private Socket socket;/*** 构造器用于初始化客户端*/public Client(){try {System.out.println(正在链接服务端...);/*Socket实例化时就是与服务端建立链接的过程此时需要传入两个参数参数1:服务端的IP地址用于找到服务端的计算机参数2:服务端口用于找到服务端程序如何查看IP地址:windows:窗口键R 打开控制台输入ipconfig查看以太网适配器-以太网找到ipv4查看自己的IP地址mac:打开[终端]程序输入/sbin/ifconfig查看自己的IP地址*/ // socket new Socket(127.0.0.1,8088);//127.0.0.1和localhost都是表示本机socket new Socket(localhost,8088);System.out.println(与服务端成功链接!);} catch (IOException e) {e.printStackTrace();}}/*** 用于客户端开始工作的方法*/public void start(){/*Socket提供的方法:OutputStream getOutputStream()通过Socket获取一个字节输出流通过向该流写出字节就可以发送给远端链接的计算机的Socket了*/try {OutputStream out socket.getOutputStream();OutputStreamWriter osw new OutputStreamWriter(out, StandardCharsets.UTF_8);BufferedWriter bw new BufferedWriter(osw);PrintWriter pw new PrintWriter(bw, true);/*write(int d)通过流向目标位置写出1个字节写出的是int值2进制的低八位*/ // out.write(1);//00000001Scanner scanner new Scanner(System.in);//首先要求用户输入一个昵称String nickname ;while(true) {System.out.println(请输入昵称:);nickname scanner.nextLine();if(nickname.trim().length() 0){pw.println(nickname);//将昵称发送给服务端break;}System.out.println(昵称不能为空);}//将接收服务端发送过来消息的线程启动ServerHandler handler new ServerHandler();Thread t new Thread(handler);t.setDaemon(true);t.start();System.out.println(开始聊天吧);while(true) {String line scanner.nextLine();if(exit.equalsIgnoreCase(line)){break;}pw.println(line);}} catch (IOException e) {e.printStackTrace();} finally {try {//socket的close方法会进行四次挥手//并且也会关闭通过socket获取的输入流和输出流socket.close();} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {//实际开发中不会在main方法中写业务逻辑main方法是静态方法会有很多不便Client client new Client();//调用构造器初始化客户端client.start();//调用start方法使客户端开始工作}private class ServerHandler implements Runnable{Overridepublic void run() {try {//通过socket获取输入流,用于读取服务端发送过来的消息InputStream in socket.getInputStream();InputStreamReader isr new InputStreamReader(in, StandardCharsets.UTF_8);BufferedReader br new BufferedReader(isr);String line;while((line br.readLine())!null){System.out.println(line);}} catch (IOException e) {}}}} 服务端 package socket;import java.io.*; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;/*** 聊天室服务端*/ public class Server {/*java.net.ServerSocket运行在服务端的ServerSocket相当于时客户中心的总机上面有若干的插座(Socket)客户端的插座就是与总机建立链接然后总机这边分配一个插座与之建立链接来保持双方通讯的。ServerSocket有两个主要工作1:创建时向系统申请服务端口以便客户端可以通过端口找到2:监听该端口一旦一个客户端链接便创建一个Socket通过它与客户端通讯*/private ServerSocket serverSocket;//存放所有客户端的输出流用于广播消息 // private ListPrintWriter allOut new ArrayList();/*存放所有客户端的输出流Mapkey:该客户端的昵称value:对应该客户端的输出流,用于给开客户端发送消息*/private MapString,PrintWriter allOut new HashMap();public Server(){try {System.out.println(正在启动服务端);/*实例化ServerSocket时需要指定向系统申请的服务端口如果该端口已经被系统的其他应用程序占据则这里会抛出异常java.net.BindException: Address already in use: bind()*/serverSocket new ServerSocket(8088);System.out.println(服务端启动完毕);} catch (IOException e) {throw new RuntimeException(e);}}public void start(){try {while(true) {System.out.println(等待客户端链接...);/*ServerSocket的重要方法:Socket accept()该方法是一个阻塞方法调用该方法后程序会卡住直到一个客户端使用Socket与服务端建立链接为止此时accept方法会立即返回一个Socket通过返回的Socket就可以与链接的客户端双向通讯了。*/Socket socket serverSocket.accept();System.out.println(一个客户端链接了!);//实例化线程任务ClientHandler handler new ClientHandler(socket);//实例化线程Thread t new Thread(handler);//启动线程t.start();}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {Server server new Server();server.start();}private class ClientHandler implements Runnable{private Socket socket;private String ip;//记录当前客户端的IP地址private String nickname;//记录当前客户端的昵称public ClientHandler(Socket socket){this.socket socket;//通过socket获取远端计算机的IP地址ip socket.getInetAddress().getHostAddress();}public void run(){PrintWriter pw null;try {/*Socket的方法:InputStream getInputStream()通过socket获取一个字节输入流读取该流就可以读取到远端计算机发送过来的数据*/InputStream in socket.getInputStream();InputStreamReader isr new InputStreamReader(in, StandardCharsets.UTF_8);BufferedReader br new BufferedReader(isr);//通过socket获取输出流并流链接为PrintWriter,为了给客户端发送消息OutputStream out socket.getOutputStream();OutputStreamWriter osw new OutputStreamWriter(out, StandardCharsets.UTF_8);BufferedWriter bw new BufferedWriter(osw);pw new PrintWriter(bw, true);//首先单独读取一行字符串客户端发送过来的第一行字符串应当是昵称nickname br.readLine();//将该客户端的输出流存入共享集合中/*每个客户端链接后,主线程都会实例化一个ClientHandler(线程任务)然后实例化一个线程来执行这个任务.当线程获取时间片后开始执行任务的run方法因此,每个线程执行到下面要操作集合的这里,需要让多个线程不能同时操作这个集合那么同步监视器必须让多个线程看到的是同一个对象.这里不能使用this,因为线程在执行ClientHandler的run方法,因此run方法中的这个this是一个ClientHandler的实例,每个线程都在执行各自ClientHandler任务的run方法,因此他们看到的ClientHandler并非同一个对象*/ // synchronized (this) {//由于他们都要操作allOut集合,因此将它作为同步监视器对象是合适的//实际开发中我们总是使用临界资源作为同步监视器对象,即:抢谁就锁谁synchronized (allOut) { // allOut.add(pw);allOut.put(nickname,pw);}sendMessage(nickname上线了当前在线人数:allOut.size());String message;while ((message br.readLine()) ! null) {//聊天信息以开始,应当是私聊if(message.startsWith()){sendMessageToSomeOne(message);}else {sendMessage(nickname [ ip ]说: message);}}} catch (IOException e) {//可以添加处理客户端异常断开的操作} finally {//处理客户端断开链接后的操作//将该客户端的输出流从共享集合allOut中删除synchronized (allOut) { // allOut.remove(pw);allOut.remove(nickname);}sendMessage(nickname下线了当前在线人数:allOut.size());//将socket关闭,释放底层资源try {socket.close();} catch (IOException e) {throw new RuntimeException(e);}}}/*** 将消息发送给所有客户端*/public void sendMessage(String message){System.out.println(message);//先在服务端控制台上输出一下//遍历要和增删互斥,迭代器要求遍历过程中不可以通过集合方法增删元素synchronized (allOut) { // for (PrintWriter o : allOut) {//发送给所有客户端for(PrintWriter o : allOut.values()){o.println(message);}}}/*** 将消息发送给指定用户(私聊)* param message 格式:对方昵称:聊天消息*/private void sendMessageToSomeOne(String message){/*张三-李四 发送一个私聊message:克晶:在吗?对方昵称:聊天消息.:.tips:.在正则表达式里表示任意一个字符是一个量词,表示前面的内容出现1次以上所以.表示1次以上的任意字符*///进行私聊格式验证if(message.matches(.:.)){//根据聊天消息,截取出对方的昵称 abc:你好String toNickname message.substring(1, message.indexOf(:));if(allOut.containsKey(toNickname)) {//对方昵称在allOut中是否存在//获取对方的输出流PrintWriter pw allOut.get(toNickname);//张三悄悄对你说:在吗?String content message.substring(message.indexOf(:) 1);pw.println(nickname悄悄对你说:content);}else{PrintWriter pw allOut.get(nickname);//用户[abc]不存在pw.println(用户[toNickname]不存在);}}else{//格式不对,则同时该客户端格式不对PrintWriter pw allOut.get(nickname);pw.println(私聊格式不对,应当是对方昵称:聊天消息);}}}}
http://www.zqtcl.cn/news/989719/

相关文章:

  • 网站访问速度优化工具网页设计模板图片大全
  • 哪里有手机网站制作公司网页设计与制作心得体会800字
  • 湖南建设厅网站首页简述网站建设的基本思路
  • 蚌埠公司做网站网站开发月薪
  • 怎么更换网站logo推荐几个没封的正能量网站
  • 开网站的宣传图片怎么做php网站建设面试
  • 哪些网站可以下载视频网站建设评价量规
  • 惠州市建设局网站网站模块设计怎么做
  • 群晖可不可以做网站用如何查询商标是否已经被注册
  • 北京欢迎你网站制作公司建设厅和应急管理厅焊工证区别
  • 如何开办网站微信公众平台号申请注册
  • 网站建设找哪个平台浦东区建设工程监督网站
  • 如何创业做网站设计公司工作室
  • 游戏网站建设多少中国煤炭建设协网站
  • 动态图表网站宁津做网站
  • 黑龙江生产建设兵团各连网站成功网站建设案例
  • 一级a做爰精免费网站肇庆网站制作软件
  • wordpress加分页北京优化生育
  • 乐至建设局网站工程项目管理软件哪个好
  • 太原公司网站建立wordpress插件直播
  • 比较有名的diy制作网站做照片视频的网站
  • 河北石家庄建设网站wordpress nginx apache
  • 上海免费网站建设品牌wordpress主题安装失败下载失败
  • 买公司的网站商城系统开发
  • 网页设计国外设计欣赏网站深夜视频在线免费
  • 做网站怎么租用服务器杭州网站建设hzyze
  • .asp 网站北京最新防疫信息
  • 网站上传用什么软件做视频教程114查询
  • 网站小图标素材网站开发需要提供哪些东西
  • 阿里巴巴国际站买家入口百度建网站多少钱