Fork me on GitHub

《互联网程序设计》 -- 第3周多线程程序设计技术

   总述,这周学了多线程,区别于单线程的拉胯操作:只能你一问,我一答的操作。多线程可以做到让线程来处理主程序的东西,使得整个程序在很多情况下不会卡死。

好了,复盘一下今天的多线程学习的东西。

什么是多线程?

百度上的定义:

在计算机体系结构中,多线程是由操作系统支持的中央处理器(或多核处理器中的单核)同时具有执行多个线程能力的方法。

 

在单个处理器上运行的具有两个执行线程的进程示意图

 

实例分析

借用我们上周的简单网络对话程序。

在我们的TCPServer程序中添加一条语句:

pw.println("From服务器:重复的消息" + msg);

启动服务器和窗体程序之后我们发送消息会发现如下问题:

 

 

 

 我们的消息存在“滞后”现象,其实这里是因为单线程在作怪,我们原本的程序只有一问一答的,receive()方法只有一次,所以只回传一条信息。

多线程的使用

既然有问题,那就要解决问题。

所以我们就要使用到多线程的方法了。

我们多线程可以在连接的时候启动了。

详细代码如下:

 1 readThread = new Thread(()->{
 2   String msg = null;
 3   //不知道服务器有多少回传信息,就持续不断接收
 4   //由于在另外一个线程,不会阻塞主线程的正常运行
 5   while ((msg = tcpClient.receive()) != null) {
 6     //lambda表达式不能直接访问外部非final类型局部变量
 7     //所以这里使用了一个临时变量
 8     String msgTemp = msg;
 9     Platform.runLater(()->{
10       taDisplay.appendText( msgTemp + "\n");
11     });
12   }
13 //跳出了循环,说明服务器已关闭,读取为null,提示对话关闭
14   Platform.runLater(()->{
15     taDisplay.appendText("对话已关闭!\n" );
16   });
17 });
18 readThread.start(); //启动线程
多线程

注意:这里要删除btnSend按钮的点击事件里接受服务器代码回传的信息,因为这部分的工作给线程去做了。不删的话会卡死整个程序。

     String receiveMsg = tcpClient.receive();//从服务器接收一行字符
     taDisplay.appendText(receiveMsg + "\n");
//这两行都要删去或注释掉

 

一些小问题

 当我们没有断开连接的时候,直接点击“退出”按钮,服务器端就会报错。

为什么呢?原因其实是在exit()函数中有两个语句:

tcpClient.send("bye");//直接发送bye,结束线程
tcpClient.close();//这里存在一个问题就是:线程还在请求,但这条语句已经执行了,所以报错

解决方法:

private void exit(){
        if(tcpClient != null){
            //向服务器发送关闭连接的约定信息
            taDisplay.appendText("bye" + "\n");

            tcpClient.send("bye");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            tcpClient.close();
        }
        System.exit(0);
    }
exit

当你不会的时候写:alt+ctrl+T,这个快捷键方便到起飞!

 

 

本周的所有代码的链接:https://wws.lanzous.com/iL6e2gtw25e

posted @ 2020-09-21 23:04  走位,走位  阅读(220)  评论(0编辑  收藏  举报