会员可以在此提问,百战程序员老师有问必答
对大家有帮助的问答会被标记为“推荐”
看完课程过来浏览一下别人提的问题,会帮你学得更全面
截止目前,同学们一共提了 132413个问题

看完了这节课的视频以后,总结了下面的内容:

这节课的视频与上次课的视频不同的点在

上次课最后实现的多线程是 多个客户端访问一个服务器的情况,为了让服务器处理多个客户端,使用循环开启多个线程,为每一个客户端开启一个线程来处理服务器端接收信息及相应信息的操作。

while(true){

      Socket socket=server.accept();//接受多个客户端的连接

      ServerThread st=new ServerThread(socket);

      new Thread(st).start();

}


这次课的多线程是客户端的多线程,是单个客户端和单个服务器端之间,单个客户端想跟单个服务器端多次聊天,如果是单次聊天,按视频里最开始的写法(没有多线程的),客户端就只能先,通过BufferedReader包装键盘录入发送信息,后获取响应,并且只有一次聊天的机会,socket就结束了。

为了解决这两个问题:

1)客户端想多次聊天

2)客户端能不能不要总是先发送,后接受信息,能主动接受信息吗?

解决:

1) 循环,循环发送信息,循环读取信息,就可以多次聊天了

2)怎么能决定先发送还是先接受,如果写成以前死的代码,就是先发送后接受,想先接受怎么办,多线程,建立一个发送线程,一个接受线程,让2个线程开启,cpu不断的切换2个线程,有内容发送到客户端来,就主动去接受,就可以先接受了。这边键盘录入,用户想发送的时候按下回车,就可以向输入流中写数据,创造输入的字符串,有内容想发送到服务端,就会触发发送线程。


我分析的视频中的代码:

image.png


一个客户端 一个服务端

服务端只接受一次的socket对象,后面的多次聊天都是因为 

客户端一直开启线程,等待用户键盘录入的回车,从而发送数据,

服务器端接收到数据就一直执行while(true),不停的readUTF() 和writeUTF("收到了");


至于我看到有同学问为什么服务器端能一直读取,我想是因为while(true)里面的readUTF()在不停执行,只要在流里读到东西就会读取出来,在流里东西可用,检测到流末尾或者抛出异常前,此方法一直阻塞,等待读取的字符串。这里需要老师验证一下我说的,是不是我分析的这个原因******。


还有一个问题******,就是在客户端线程类:Send类的send方法中写出字符串的时候,为什么要flush一下。

我猜是因为:这里也需要老师解答一下:

1)每次写出之后flush是为了提高效率,如果一直不flush,缓冲区如果满了就会造成缓冲区堵塞

2)视频里的案例没有关闭流,关闭流的操作里会刷新,但是没有关闭流,一直开着,所以在这里刷新一下。

ps:

什么时候字节流需要刷新:

如果你的流入数据不是特别多,可以都操作结束了关流时写入,那么如果你的数据特别多,你把他们全都放到流中就会占用内存吧,如果占用够多就会死机吧?然后结果你明白了!你读取数据失败了!或者説你担心万一死机了数据没有保存不是很坑!所以你可以选择什么时候刷新下

所以当传入的数据特别大,又担心什么时候会突然停止的时候,字节流可以在某些地方刷新一下。

image.png


以上提到的两个地方都需要老师解答一下(带******号的),还有提到的其他地方如果有不太对的地方,也希望老师指导一下,谢谢!

JAVA 全系列/第二阶段:JAVA 基础深化和提高/网络编程(旧) 3106楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/网络编程(旧) 3107楼

老师,请问为什么会报错啊

package com.bjsxt;

import java.util.Arrays;
import java.util.EmptyStackException;

/*
自定义栈容器
 */

public class MyStack<E> {
    private Object[] arr;       //存放元素的物理结构

    private int stackLength = 4;   //数组的默认长度

    private int size;          //记录栈容器的元素个数

    private int index = -1;       //操作数组下标的指针


    //判断栈容器是否为空
    public boolean empty() {
        return this.size==0;

    }


    //获取栈顶元素
    public E pop() {
        //如果栈容器中没有元素则抛出异常
        if (this.index == -1) {
            throw new EmptyStackException();
        }
        //记录元素个数
        this.index--;
        //如果有元素,则返回栈顶元素
        return (E) this.arr[index--];
    }


    //向栈顶添加元素
    public E push(E item) {
        //初始化数组
        this.capacity();
        //向数组中添加元素
        this.arr[++index] = item;
        //记录元素个数
        this.size++;
        return item;
    }


    //数组初始化或者以1.5倍容量对数组扩容
    private void capacity() {
        //数组初始化
        if (this.arr == null) {
            this.arr = new Object[this.stackLength];
        }
        //以1.5倍对数组扩容
        if (this.size - this.stackLength >= 0) {
            this.stackLength = this.stackLength + this.stackLength >> 1;   //>>右位移一位等于除以2
            this.arr = Arrays.copyOf(this.arr, this.stackLength);
        }
    }


    public static void main(String[] args) {
        MyStack<String> myStack=new MyStack<>();
        myStack.push("a");
        myStack.push("b");
        myStack.push("c");

        System.out.println(myStack.size);

        System.out.println(myStack.pop());
        System.out.println(myStack.pop());



    }

}


JAVA 全系列/第二阶段:JAVA 基础深化和提高/数据结构 3108楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/容器 3109楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/IO 流技术(旧) 3113楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/手写服务器项目(旧) 3114楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/IO 流技术(旧) 3115楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/异常机制 3116楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/常用类 3117楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/容器(旧) 3119楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/XML 技术(旧) 3120楼

课程分类

百战程序员微信公众号

百战程序员微信小程序

©2014-2025百战汇智(北京)科技有限公司 All Rights Reserved 北京亦庄经济开发区科创十四街 赛蒂国际工业园
网站维护:百战汇智(北京)科技有限公司
京公网安备 11011402011233号    京ICP备18060230号-3    营业执照    经营许可证:京B2-20212637