多线程编程和Java网络编程
1. 线程概述
多任务处理有两种类型:基于进程、基于线程(进程是指一种“自包容”的运行程序,有自己的地址空间; 线程是进程内部单一的一个顺序控制流)
基于进程的特点是允许计算机同时运行两个或更多的程序、基于线程的多任务处理环境中,线程是最小的处理单位
2. 创建和启动线程
a. 编写一个继承Thread 类的类,然后重写Thread类的run()方法
public class thread extends Thread {
public void run() {
}
public static void main(String[] args) {
thread d = new thread();
d.start();
}
}
b. 编写一个类实现Runnable接口,然后将该类的实例与Thread对象联系在一起
public class threadrun implements Runnable { public void run(){
}
public static void main(String[] args) {
threadrun td = new threadrun();
Thread t = new Thread(td);
t.start();
}
}
3. 线程的优先级
A. Java 中的线程优先级是在 Thread 类中定义的常量:
NORM_PRIORITY : 值为 5
MAX_PRIORITY : 值为 10
MIN_PRIORITY : 值为 1
B . 有关优先级的方法有两个:
a. final void setPriority(int newp) : 修改线程的当前优先级
b. final int getPriority() : 返回线程的优先级
4. 使线程暂停执行的条件
A. 使用 sleep( ) 方法使线程睡眠
B. 通过调用 wait( ) 方法,使线程等待
C. 通过调用 yield( ) 方法,线程已显式出让CPU控制权
D. 线程由于等待一个I/O事件被阻塞
5. 线程同步:使用同步关键字synchronized
A.解决线程同步的方法:
a. 同步块
语法:synchronized (取得锁的对象){
//要锁定的代码
}
b.同步方法:在方法名关键字修饰前面使用synchronized
6. 死锁: 当两个线程循环依赖于一对同步对象时将发生死锁
7. 线程之间的相互通讯
方法:
a . 网络编程的实质就是编写程序直接或间接地通过网络协议与其它计算机上的某个程序进行通讯
b. 如何找到网络上的主机上的要进行通讯的程序 ?
c. 提供了IP地址和端口号,就可以找到网络上指定主机上要进行通讯的指定程序
a. 数据传输由TCP/IP分层模型中的传输层负责,该层包含TCP和UDP两种协议
b. TCP协议:较可靠的双向流协议、发送任意数量的数据、提供消息确认、错误检测和错误恢复等服务
c. UDP协议:比较不可靠
10 . 客户端和服务器
A. 服务器和客户端共同承担计算
a. 客户:向另一台计算机请求服务的计算机
b. 服务器:处理客户端请求的计算机
JDK预定义的网络编程相关类均存放在java.net包中。
常用的类:InetAddress 、Socket、ServerSocket 和 SocketImpl、DatagramPacket 和 DatagramSocket、 URL、URLConnection 和 URLEncoder
该类没有构造方法,所以不能直接利用new 关键字创建对象。我们可以使用以下常用方法来获取该类对象:
getLocalHost():返回表示本地主机InetAddress对象
getByName(String hostName):据主机名返回对象
getAddress() :返回IP地址
getHostName():取得IP地址代表的主机名
两个java程序通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称之为Socket( Socket通常用来实现客户服务器之间的连接)
java.net包中的两个类Socket、ServerSocket分别用来实现客户端和服务端
A. 服务端( ServerSocket )编写步骤:
1).利用ServerSocket建立对服务端某个端口的监听
2).利用accept方法创建服务端Socket
3).利用已建立的socket创建输入输出流
4).关闭输入输出流,关闭socket,关闭server
B. 客服端( Socket )编写步骤:
1).创建客户端Socket向服务器发起连接请求
2).利用已建立的socket创建输入输出流
3).关闭输入输出流,关闭socket,关闭server
A. 用户报文协议(UDP)是用于将二进制数据从一台计算机发送到另一台计算的非连接协议
B. 数据报包的发送者和接收者都使用java.net.DatagramSocket类分别发送和接收包
D. 接收数据报包需要执行如下步骤:
1). 创建一个足够大的字节数组,用于存储要接收的包的数据
2). 使用该字节数组实例化一个DatagramPacket对象
3). DatagramSocket被实例化,它被指定该套接字要绑定到的本地主机上的一个端口
4). 调用DatagramSocket类的receive()方法,将DatagramPacket对象传入该方法。这将导致执行线程阻塞,直到接收到一个数据报包或者发生了超时
E. 发送数据报包需要执行如下步骤:
1). 创建一个足够大的字节数组,用于存储要发送的包数据,用该数据填充数组
2). 创建一个新的DatagramPacket 对象,用于存储上面的字节数组,以及服务器名和接收者的端口号
3). DatagramSocket被实例化,它被指定套接字要绑定到本地主机的哪个端口
4). DatagramSocket类的send()方法被调用,传入DatagramPacket对象
例题:简易局域网聊天系统–局域网QQ:
服务器端
实现简易的启动停止服务器端操作,能记录基本日志:客户连接、消息传送,能查看连接客户的昵称。
启动服务器后开始监听客户端连接,创建一个新线程实现该监听操作。
// 启动新线程监听客户端
new Thread(new Runnable() {
public void run() {
writeLog("开始监听客户端:");
listen();
}
}).start();
为每一个客户端连接开启一个新线程处理通讯,包括处理输入流与输出流。
// 每监听到一个客户端连接,启动一个新线程处理该连接
new Participant(this, socket, usersList).start();
获取用户不同的行为实现不同的操作 String flag = in.readUTF();
// 获取用户操作行为
if ("validateUser".equals(flag)) { // 验证用户是否存在
// ……………………
} else if ("newUser".equals(flag)) { // 新用户登录
// ……………………
} else if ("message".equals(flag)) { // 用户间发送消息
// ……………………
} else if ("userList".equals(flag)) { // 获取用户列表
// ……………………
}
在服务器端,采用Map保存每个客户端对应的套接字:
private Map<String, Socket> usersList = new HashMap<String, Socket>();
key为客户端连接时输入的用户昵称,value为对应的套接字对象。
各客户端用户间发送消息时,通过服务器转发送该信息:
String sender = in.readUTF(); // 发送者
String receiver = in.readUTF(); // 接收者
String message = in.readUTF(); // 消息
// 添加日志
server.writeLog(sender + " 向 " + receiver + "发送消息:" + message);
// 服务器向目标转发消息,先获得要转发后的目标套接字对象
Socket socket = server.getUsersList().get(receiver);
System.out.println(out);
if (socket == null) { // 服务器已删除该客户端连接信息
out.writeUTF("message");
out.writeUTF("系统服务器");
out.writeUTF(receiver + "已退出系统,无法再发送消息");
out.flush();
} else {
DataOutputStream thatOut = new DataOutputStream(socket.getOutputStream()); // 创建输出流对象
if (thatOut != null) {
thatOut.writeUTF("message");
thatOut.writeUTF(sender);
thatOut.writeUTF(message);
thatOut.flush(); // 写入客户端输出流中
}
}
客户端
先通过登录窗体实现服务器端连接,然后输入登录用户昵称,如果服务器端还未保存该昵称,则登录成功。登录成功后,可以直接先读取到服务器端已有登录用户的昵称,显示到列表中。双击好友列表中的任一项打开聊天对话框,然后双方可以开始聊天。
创建到服务器的套接字对象:
// 创建套接字对象
socket = new Socket(serverIp.getText().trim(), Integer.parseInt(port.getText().trim()));
连接的服务器与端口从窗体文本框中获取到。
登录成功后,将昵称发送到服务器保存:
out.writeUTF("newUser");
out.writeUTF(nickname); out.flush();
刷新好友列表:
// 读取流中信息
String flag = in.readUTF();
if ("userList".equals(flag)) { // 好友列表
String[] userList = in.readUTF().split("::::"); // 获取好友列表,使用标记分隔
// 创建好友列表模型
DefaultListModel list = new DefaultListModel();
for (int i = 0; i < userList.length; i++) {
list.addElement(userList[i]);
}
friends.setModel(list); // 设置模型
friends.validate(); // 重绘
}
发送消息给某个好友:
out.writeUTF("message");
out.writeUTF(sender);
out.writeUTF(recipient);
out.writeUTF(textArea.getText());
out.flush();
开启新线程读取服务器转发的好友信息:
String flag = in.readUTF();
if ("message".equals(flag)) {
String sender = in.readUTF();
String msg = in.readUTF();
String message = sender + " 对你说:" + msg + "\n";
jTextArea.append(message);
}
多线程编程和Java网络编程的更多相关文章
- Java-Runoob-高级编程:Java 网络编程
ylbtech-Java-Runoob-高级编程:Java 网络编程 1.返回顶部 1. Java 网络编程 网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来. java.n ...
- Java网络编程和NIO详解开篇:Java网络编程基础
Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...
- Java工程师学习指南第5部分:Java网络编程与NIO
本文整理了微信公众号[Java技术江湖]发表和转载过的Java网络编程相关优质文章,想看到更多Java技术文章,就赶紧关注本公众号吧. 深度解读 Tomcat 中的 NIO 模型 [Java基本功]浅 ...
- day05 Java网络编程socket 与多线程
java网络编程 java.net.Socket Socket(套接字)封装了TCP协议的通讯细节,是的我们使用它可以与服务端建立网络链接,并通过 它获取两个流(一个输入一个输出),然后使用这两个流的 ...
- java 网络编程复习(转)
好久没有看过Java网络编程了,现在刚好公司有机会接触,顺便的拾起以前的东西 参照原博客:http://www.cnblogs.com/linzheng/archive/2011/01/23/1942 ...
- java网络编程serversocket
转载:http://www.blogjava.net/landon/archive/2013/07/24/401911.html Java网络编程精解笔记3:ServerSocket详解ServerS ...
- Java 网络编程(转)
一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可 ...
- 【Java基础】Java网络编程基础知识
什么是网络编程 网络编程是通过使用套接字来达到进程间通信目的,那什么是套接字呢?其实套接字是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的 ...
- 【Java】Java网络编程菜鸟进阶:TCP和套接字入门
Java网络编程菜鸟进阶:TCP和套接字入门 JDK 提供了对 TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Datagram Protoco ...
随机推荐
- js 攻坚克难
new new : 官方解释: 如果在一个函数前面带上new来调用,那么背地里将会创建一个连接到该函数的prototype的成员的新对象,同时this会被绑定到哪个新对象上: new 是用来创建对象的 ...
- codeforces_724C_Ray Tracing
C. Ray Tracing time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...
- 获取webconfig配置文件内容
string ServerUrl= ConfigurationManager.AppSettings["ServerUrl"].ToString(); web.config中的配置 ...
- 【剑指Offer】65、矩阵中的路径
题目描述: 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经 ...
- sqlalchemy子查询
使用subquery() 要使用c来定位上一个子句的属性 s1 = session.query(m.a,m.b).filter().subquery() s2 = session.query(s1.c ...
- python下操作mysql 之 pymsql
python下操作mysql 之 pymsql pymsql是Python中操作MySQL的模块, 下载安装: pip3 install pymysql 使用操作 1, 执行SQL #!/usr/ ...
- 6.3.4 使用marshal 模块操作二进制文件
Python 标准库 marshal 也可以进行对象的序列化和反序列化,下面的代码进行了简单演示. import marshal x1 = 30 x2 = 5.0 x3 = [1,2,3] x4 = ...
- vue 组件通信传值
父子组件通信: 子组件 <template> <div> <h3 @click="alerrt"> 我是子组件一</h3> < ...
- 【Codeforces 385C】Bear and Prime Numbers
[链接] 我是链接,点我呀:) [题意] f[i]表示在x[]中有多少个数字是i的倍数 让你求出sum(f[i]) li<=i<=ri 且i是质数 [题解] 做筛法求素数的时候顺便把素数i ...
- ACDream - Chasing Girl
先上题目: Chasing Girl Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) ...