比较规则里return 1和return -1有什么用啊
老师,一对多聊天服务中,我的客户端不是每次都能返回消息。
下面的是服务端的代码
package com.bjsxt.ls.网络编程.TCP.一对多聊天服务器; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; //创建服务端接收消息的线程 class ChatReceive extends Thread{ private Socket ss; public ChatReceive(Socket n){ this.ss=n; } @Override public void run() { this.receive1(); } //创建接收消息的线程 public void receive1(){ BufferedReader br =null; try { br = new BufferedReader(new InputStreamReader(this.ss.getInputStream())); while (true){ String jieshou = br.readLine(); synchronized ("同步锁") { //要让发送消息和接收消息的线程处于同步状态,需要在两个线程上加上同一个名字的对象锁 ChatServer.BUF = jieshou; //将接收到的消息保存到缓存区 "同步锁".notify(); //当消息存到缓存区之后,唤醒发送消息线程,可以发送消息了 } } } catch (IOException e) { e.printStackTrace(); }finally { if (br != null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (this.ss != null){ try { ss.close(); } catch (IOException e) { e.printStackTrace(); } } } } } //创建服务端发送消息的线程类 class ChatSend extends Thread{ private Socket ss; public ChatSend(Socket n){ this.ss=n; } @Override public void run() { this.send1(); } //创建发送消息的方法 public void send1(){ PrintWriter pw = null ; try { pw = new PrintWriter(this.ss.getOutputStream()); while (true) { synchronized ("同步锁") { //要让发送消息和接收消息的线程处于同步状态,需要在两个线程上加上同一个名字的对象锁 "同步锁".wait(); //发送消息的线程应先处于等待状态 pw.println(ChatServer.BUF); //将消息从缓存区取出,因为BUF是static的,直接用类名就能调用 pw.flush(); } } } catch (Exception e) { e.printStackTrace(); }finally { if (pw != null){ pw.close(); } if (this.ss != null){ try { this.ss.close(); } catch (IOException e) { e.printStackTrace(); } } } } } //主线程用于启动服务端,客户端可以使用之前的“点对点优化”中的GoodP2P public class ChatServer { //定义一个字符串类型的缓存区 public static String BUF; public static void main(String[] args) { System.out.println("正在启动服务器....."); System.out.println("<HappyDay>聊天室启动"); ServerSocket serverSocket = null; try { serverSocket =new ServerSocket(332); while (true){ Socket sk =serverSocket.accept(); //将启动服务端放在循环中,因为每次发送或接收消息都需要启动服务端 System.out.println("已经连接到IP地址为["+ InetAddress.getLocalHost() +"]的主机。"); new ChatReceive(sk).start(); //启动线程 new ChatSend(sk).start(); } } catch (IOException e) { e.printStackTrace(); }finally { if(serverSocket!=null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
这个是用的优化的点对点聊天作为客户端的代码
package com.bjsxt.ls.网络编程.TCP.点对点优化; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; //创建发送消息线程 class send1 extends Thread{ private Socket socket =null; private Scanner scanner =null; public send1(Socket s1,Scanner s2){ this.socket =s1; this.scanner=s2; } //创建发送消息的方法 public void sengmessage(){ PrintWriter pw =null; try{ pw =new PrintWriter(socket.getOutputStream()); scanner = new Scanner(System.in); while (true){ String say =scanner.nextLine(); pw.println(say); pw.flush(); } }catch (Exception e){ e.printStackTrace(); }finally { if (pw != null){ pw.close(); } if (scanner != null){ scanner.close(); } if (socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public void run() { this.sengmessage(); } } //创建接收消息的线程 class receive extends Thread{ private Socket socket =null; public receive(Socket x){ this.socket = x; } public void receivemessage(){ BufferedReader br= null; try { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); while (true){ String rs = br.readLine(); System.out.println("收到的消息是:"+rs); } } catch (IOException e) { e.printStackTrace(); }finally { if (br != null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket!= null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public void run() { this.receivemessage(); } } public class GoodP2P { public static void main(String[] args) { Scanner scanner = null; ServerSocket serverSocket = null; Socket socket = null; scanner =new Scanner(System.in); System.out.println("请输入:server,<port> 或者:" + "<ip>,<port>"); String str = scanner.nextLine(); String arr[] =str.split(",");//以逗号为分割点存入数组 //判断当输入的server时,启动服务端 if ("server".equals(arr[0])){ System.out.println("TCP点对点通信,正在启动服务端,连接端口号["+arr[1]+"]"); try { serverSocket =new ServerSocket(Integer.parseInt(arr[1]));//将字符串强转为整型 socket = serverSocket.accept(); } catch (IOException e) { e.printStackTrace(); } System.out.println("连接成功!"); } //当输入的不是server时,即进入客户端 else { try { socket = new Socket(arr[0],Integer.parseInt(arr[1])); System.out.println("连接成功!"); } catch (IOException e) { e.printStackTrace(); } } //启动发送消息的线程 new send1(socket,scanner).start(); new receive(socket).start(); if (serverSocket != null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
下面的运行的截图:
服务端测试
客户端1
客户端2
客户端3
老师,我现在才发现为什么我的idea全是英文的呀
老师那里有问题呀
想问下一定要调用FileOutputStream的flush()方法吗,没有写这个方法的时候程序也正常运行了。
老师,为什么在放馒头的同步方法里,用notify()唤醒的是取馒头的线程呢?
截屏2021-09-03 下午3.51.45.png
同楼上,一样的报错,不知原因
通过socket的顺序,和之前将的TCP的三次握手有什么区别?
这里是从服务器ServerSocket开始创建。
但是在讲TCP建立连接的三次握手时,有说的是从客户端发送TCP保文。
为什么这两个开始是从不同的方向?这两个的作用有什么区别?
老师,在添加序列化编码时,鼠标放在类名这出现指示,有两个序列化编码提示,而且添加的编码不同,我是该选哪一个?
老师为什么我写入的数据的内容超过四个字,在文件里显示的就是乱码
文本的格式我也设置gbk了,难道内容容量需要设置吗?
package com.bjsxt.dead; public class DeadLock extends Thread{ private Object money; private Object water; public boolean flag;//标识持有对象锁 public DeadLock(Object money, Object water) { super(); this.money = money; this.water = water; } @Override public void run() { if(flag) { synchronized (money) { System.out.println("有钱,等水"); try { Thread.sleep(300); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } synchronized (water) { System.out.println("有水,等钱"); } } }else { synchronized(water) { System.out.println("有水,等钱"); try { Thread.sleep(300); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); } }synchronized (money) { System.out.println("有钱,等水"); } } } public static void main(String[] args) { Object money=new Object(); Object water=new Object(); DeadLock d1=new DeadLock(money, water); DeadLock d2=new DeadLock(money, water); d1.flag=true; d2.flag=false; d1.start(); d2.start(); } }
老师我这个嵌套的,应该会产生死锁,怎么还会打出后面的三四句
Test3 { main(String[] args) { List list = ArrayList<>(); list.add(); list.add(); list.add(); list.add(); list.sort((o1,o2) -> o1.compareTo(o2)); } } }
为什么compareTo报红
老师我这里为何会报异常,请老师帮忙看看谢谢,学到这,我有点迷糊了,有点听不懂了
package com.bjsxt.server; import java.util.List; import java.util.Map; import org.dom4j.Element; import com.bjsxt.servelet.Servlet; /** * 编写WebApp类 * @author ADMIN *(1)初始化程序运行的数据 *(2)根据不同的url创建所请求的Servlet对象 */ public class WebApp {//App的意思就是应用程序 private static ServletContext contxt; //使用静态块初始化Servlet容器 static{ contxt=new ServletContext(); //分别获取对应关系的Map集合 Map<String,String>servlet=contxt.getServlet(); Map<String,String>mapping=contxt.getMapping(); //创建解析XML文件的对象 webDom4j web=new webDom4j(); web.parse(web.getDocument());//解析xml //获取解析XML之后的List集合 List<Entity>entityList=web.getEntityList(); List<Mapping>mappingList=web.getMappingList(); //将List集合中的数据存储到Map集合中去 for (Entity entity : entityList) { servlet.put(entity.getName(), entity.getClazz()); } //System.out.println(servlet); for(Mapping map:mappingList){ //遍历url-pattern的集合 List<String>urlPattern=map.getUrlPattern(); for(String s:urlPattern ){ mapping.put(s, map.getName()); } } //System.out.println(mapping); } /** * 根据url创建不同的Servlet对象 * @param url * @return */ public static Servlet getServlet(String url){ if(url==null||url.trim().equals("")){ return null; } //调用无参构造方法创建Servlet对象 try { //如果url正确 //根据url的key获取Servlet -name的值/log=login, /reg=register String servletName=contxt.getMapping().get(url); //根据servletName得到对应的servlet-class String servletClass=contxt.getServlet().get(servletName);//得到的是一个完整的包名+类名的字符串 //使用反射创建Servlet对象 Class<?>clazz=Class.forName(servletClass); Servlet servlet = (Servlet) clazz.newInstance(); return servlet; } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public static void main(String[] args) { System.out.println(getServlet("/log")); } }
划红线的地方为什么可以这么用 怎么来的 可以解释一下吗
class ManTou { private int id; public ManTou(int id) { this.id = id; } public int getId() { return this.id; } } /** * 定义缓冲区类 */ class SyncStack { //定义存放馒头的盒子 private ManTou[] manTous = new ManTou[10]; //定义操作盒子的索引 private int index; /** * 放馒头的方法 */ public synchronized void put(ManTou manTou) { //判断盒子是否已满 while (this.index == this.manTous.length) { try { this.wait(); //wait()必须在synchronized块中调用 wait()执行后 线程会将持有的对象锁释放 并进入阻塞状态 其他需要该对象锁的线程就可以继续运行了 } catch (InterruptedException e) { e.printStackTrace(); } } //唤醒取馒头的线程 this.notify(); //该方法必须在synchronized块中调用 会唤醒处于等待状态队列中的一个线程 this.manTous[this.index] = manTou; this.index++; } /** * 取馒头的方法 */ public synchronized ManTou get() { //判断盒子是否已空 while (this.index == 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notify(); this.index--; return this.manTous[this.index]; } } /** * 定义生产者线程类 */ class ShengChan extends Thread { private SyncStack syncStack; public ShengChan(SyncStack syncStack) { this.syncStack = syncStack; } @Override public void run() { for (int i = 0; i < 10; i++) { ManTou manTou = new ManTou(i); syncStack.put(manTou); System.out.println("生产第"+(i+1)+"个馒头"); } } } /** * 定义消费者线程类 */ class Xiaofei extends Thread { private SyncStack syncStack; public Xiaofei(SyncStack syncStack) { this.syncStack = syncStack; } @Override public void run() { for (int i = 0; i < 10; i++) { ManTou manTou = this.syncStack.get(); System.out.println("消费了" + (i+1) + "个馒头"); } } } public class ProduceThread { public static void main(String[] args) { SyncStack syncStack = new SyncStack(); new ShengChan(syncStack).start(); new Xiaofei(syncStack).start(); } }
老师为什么我这里会出现先消费的现象啊?
非常抱歉给您带来不好的体验!为了更深入的了解您的学习情况以及遇到的问题,您可以直接拨打投诉热线:
我们将在第一时间处理好您的问题!
关于
课程分类
百战程序员微信公众号
百战程序员微信小程序
©2014-2025百战汇智(北京)科技有限公司 All Rights Reserved 北京亦庄经济开发区科创十四街 赛蒂国际工业园网站维护:百战汇智(北京)科技有限公司 京公网安备 11011402011233号 京ICP备18060230号-3 营业执照 经营许可证:京B2-20212637