总述,这周学了多线程,区别于单线程的拉胯操作:只能你一问,我一答的操作。多线程可以做到让线程来处理主程序的东西,使得整个程序在很多情况下不会卡死。
好了,复盘一下今天的多线程学习的东西。
什么是多线程?
百度上的定义:
在计算机体系结构中,多线程是由操作系统支持的中央处理器(或多核处理器中的单核)同时具有执行多个线程能力的方法。
在单个处理器上运行的具有两个执行线程的进程示意图
实例分析
借用我们上周的简单网络对话程序。
在我们的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 + " "); 11 }); 12 } 13 //跳出了循环,说明服务器已关闭,读取为null,提示对话关闭 14 Platform.runLater(()->{ 15 taDisplay.appendText("对话已关闭! " ); 16 }); 17 }); 18 readThread.start(); //启动线程
注意:这里要删除btnSend按钮的点击事件里接受服务器代码回传的信息,因为这部分的工作给线程去做了。不删的话会卡死整个程序。
String receiveMsg = tcpClient.receive();//从服务器接收一行字符 taDisplay.appendText(receiveMsg + " "); //这两行都要删去或注释掉
一些小问题
当我们没有断开连接的时候,直接点击“退出”按钮,服务器端就会报错。
为什么呢?原因其实是在exit()函数中有两个语句:
tcpClient.send("bye");//直接发送bye,结束线程 tcpClient.close();//这里存在一个问题就是:线程还在请求,但这条语句已经执行了,所以报错
解决方法:
private void exit(){ if(tcpClient != null){ //向服务器发送关闭连接的约定信息 taDisplay.appendText("bye" + " "); tcpClient.send("bye"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } tcpClient.close(); } System.exit(0); }
当你不会的时候写:alt+ctrl+T,这个快捷键方便到起飞!
本周的所有代码的链接:https://wws.lanzous.com/iL6e2gtw25e