线程通信 ????????多线程之间打成通信沟通的效果,协作完成业务需求
????Object: ????????wait() 线程等待 ?当调用某一个对象 的wait方法,当前线程就会进入到与这个对象相关的等待池中进行等待--->等待阻塞,等待被唤醒 ????????????会让出cpu的资源,并且会释放对象的锁 ????????notify() 唤醒线程 ?当调用一个对象的notify方法,会唤醒当前对象等待池中正在等待的线程,唤醒某一个 ????????????这个线程会进入到就绪状态,要想要运行: 1)cpu的调度 ???2)获取对象锁
????????wait(ms) ???阻塞等待指定时间 ????????notifyAll() 唤醒全部
????????wait与notify必须使用在一个同步环境下,用于控制多线程之间协调工作问题,保证数据安全
????????sleep与wait之间区别 ????????????sleep : 线程休眠 ?抱着资源睡觉: 让出cpu资源,抱着对象的锁
????人车共用街道: ????????街道 : 红绿灯 boolean flag ??绿灯-->人走 ?true ??????????红灯-->车走 ?false ??ns南北走向 ??we东西走向 ????????人 : ns南北 ????????车 : we东西
????生产者消费者模式: ????????通过信号灯法 ?*/ public class Class001_Wait { ????public static void main(String[] args) { ????????Street street = new Street(); //共享街道 ????????new Thread(new Person(street)).start(); ????????new Thread(new Car(street)).start(); ????} }
//街道 class Street{ ????//红绿灯 ????private boolean flag = false;
????//ns ????public synchronized void ns(){ ????????//判断是否为绿灯 ????????if(flag){ ???????????/* try { ????????????????Thread.sleep(1000); ????????????} catch (InterruptedException e) { ????????????????e.printStackTrace(); ????????????}*/ ????????????System.out.println("人走......"); ????????????//红绿灯变为红灯 ????????????flag=false; ????????????//唤醒对方线程 ????????????this.notify(); ????????????//自己等待 ????????????try { ????????????????this.wait(); ????????????} catch (InterruptedException e) { ????????????????e.printStackTrace(); ????????????}
????????} ????}
????//we ????public synchronized void we(){ ????????if(!flag){ ????????????/*try { ????????????????Thread.sleep(1000); ????????????} catch (InterruptedException e) { ????????????????e.printStackTrace(); ????????????}*/ ????????????System.out.println("车走......"); ????????????//红绿灯变为红灯 ????????????flag=true; ????????????//唤醒对方线程 ????????????this.notify(); ????????????//自己等待 ????????????try { ????????????????this.wait(); ????????????} catch (InterruptedException e) { ????????????????e.printStackTrace(); ????????????} ????????} ????} } //人 class Person implements Runnable{ ????//街道 ????private Street street = null;
????public Person(Street street) { ????????this.street = street; ????}
????@Override ????public void run() { ????????while(true){ ????????????street.ns(); ????????} ????} }
//车 class Car implements Runnable{ ????//街道 ????private Street street = null;
????public Car(Street street) { ????????this.street = street; ????}
????@Override ????public void run() { ????????while(true){ ????????????street.we(); ????????} ????} }
????网页编程 : 上层的应用 ????网络编程 : 底层,关注数据如何传输,如何存储 ????????节点 : 网络电子设备 ????????节点与节点之间组成网络 ????????IP : 表示节点 ????????端口 : 区分不同的软件 ????????URL : 互联网中资源的指针,统一资源定位符 ????????协议 : 合同,标准,规范 ????????传输层协议 : ????????????UDP : 相当于写信 ?只管写只管发 ?效率高 ??不安全 ?大小存在限制 ????????????TCP : 相当于打电话 ?面向连接 ?安全性高 ?效率低 ??大小没有限制 ?****
????IP : ????????定义网络中的节点 (网络电子设备,手机,电脑,路由器...) ????????分为 : IPV4(4个字节,32位) ?IPV6 (128位) ????????特殊IP: ????????????192.168.0.0~192.168.255.255 ?非注册IP,供组织内部使用 ????????????127.0.0.1 本地IP ????????????localhost : 本地域名 ????????????域名与IP之间的关系: ?DNS解析器
????????java.net包 ????????InetAddress ?类表示Internet协议(IP)地址
?*/ public class Class001_IP { ????public static void main(String[] args) throws UnknownHostException { ????????//static InetAddress getByName(String host) 根据主机名称确定主机的IP地址。 ????????//static InetAddress getLocalHost() 返回本地主机的地址。 ????????InetAddress address1 = InetAddress.getLocalHost(); ????????System.out.println(address1); //DESKTOP-KHNV6UD/192.168.16.236 ????????System.out.println(address1.getHostName()); ????????System.out.println(address1.getHostAddress());
????????InetAddress address2 = ?InetAddress.getByName("www.baidu.com"); ????????System.out.println(address2); ????????System.out.println(address2.getHostName()); ????????System.out.println(address2.getHostAddress()); ????} }
IP : 定位节点 ????端口 : 区分软件 ????????端口号 2个字节 ?0~65535 ????????同一协议下端口号不能冲突 ????????建议使用8000以上的,8000以下称为预留端口号
????常见的端口: ????????80 : http ????????8080 : tomcat ????????1521 : Oracle ????????3306 : Mysql
????InetSocketAddress 此类实现IP套接字地址(IP地址+端口号)它也可以是一对(主机名+端口)
? public class Class002_Port { ????public static void main(String[] args) ?{ ????????//InetSocketAddress(String hostname, int port) 根据主机名和端口号创建套接字地址。 ????????//InetSocketAddress(InetAddress addr, int port) 根据IP地址和端口号创建套接字地址。 ????????InetSocketAddress in = new InetSocketAddress("localhost",8989); ????????System.out.println(in); ????????System.out.println(in.getHostName()); ????????System.out.println(in.getPort()); ????} }
?URL ????????同一资源定位符,指向万维网上的“资源”的指针。
????组成: ????????协议: http ????????域名: www.baidu.com ????????端口号: 80 ????????资源: index.html ????????????提交数据: name=zhangsan&pwd=123 ????????????锚点: #a
????互联网 的三大基石: ????????html ????????http ????????url
?????URL 类
? public class Class003_URL { ????public static void main(String[] args) throws MalformedURLException { ????????//URL(String spec) 从 String表示创建 URL对象。 ????????//URL(String protocol, String host, int port, String file) ????????URL url = new URL("https://www.baidu.com:80/index.html?name=zhangsan&pwd=123#a");
????????System.out.println(url); ????????System.out.println("协议:"+url.getProtocol()); ????????System.out.println("域名:"+url.getHost()); ????????System.out.println("端口:"+url.getPort()); ????????System.out.println("资源:"+url.getFile()); ????????System.out.println("资源:"+url.getPath()); ????????System.out.println("资源:"+url.getQuery()); ????????System.out.println("资源:"+url.getRef()); ????} }
网络爬虫
public class Class004_Spider { ????public static void main(String[] args) throws IOException { ????????//1.定义URL ????????URL url = new URL("https://www.baidu.com/index.html"); ????????//2.获取流 : InputStream openStream() 打开与此 URL的连接并返回 InputStream以从该连接读取。 ????????InputStream is = url.openStream(); ????????//InputStreamReader 字节输入流转位字符输入流的节点流-->功能流 ????????BufferedReader rd = new BufferedReader(new InputStreamReader(is)); ????????String msg = null; ????????//3.读入操作 ????????while((msg = rd.readLine())!=null){ ????????????System.out.println(msg); ????????} ????????//4.关闭 ????????rd.close(); ????????is.close(); ????} }
?套接字: ????????传输层为应用层开辟的小口子 ????????不同协议下Socket实现不同 ????????UDP与TCP协议对Socket实现
????UDP : 相当于写信|有包裹|发短信 ?非面向连接 ??协议简单,开销小,效率高 ??不安全 ???大小由限制(一般不超过60k) ????TCP : 相当于打电话 ??????面向连接 ???效率低 ?安全 ?????大小没有限制 ????????基于三次握手
????UDP协议下发送端与接收端两端平等 ????DatagramSocket ?此类表示用于发送和接收数据报包的套接字。 ????????DatagramSocket(int port) 构造一个数据报套接字并将其绑定到本地主机上的指定端口。 ????????void receive(DatagramPacket p) 从此套接字接收数据报包。 ????????void send(DatagramPacket p) 从此套接字发送数据报包。
????DatagramPacket 该类表示数据报包。 ????????byte[] getData() 返回数据缓冲区。 ????????int getLength() 返回要发送的数据的长度或接收的数据的长度。
????数据的传输基于字节数组
????UDP实现发送端: 基本流程 ????????1.定义我是发送端 ????????2.准备数据 ????????3.打包 ????????4.发送 ????????5.关闭
?*/ public class Class001_Send { ????public static void main(String[] args) throws IOException { ????????// 1.定义我是发送端 ????????DatagramSocket s = new DatagramSocket(9090);
????????System.out.println("-------------我是发送端-------------");
????????// 2.准备数据 ????????byte[] arr = "你好".getBytes(); ????????// 3.打包 ????????DatagramPacket packet = new DatagramPacket(arr,0,arr.length,new InetSocketAddress("127.0.0.1",8989)); ????????// 4.发送 ????????s.send(packet); ????????// 5.关闭 ????????s.close(); ????} }
public class Class002_Receive { ????public static void main(String[] args) throws IOException { ????????//1.定义我是接收端 ????????DatagramSocket r = new DatagramSocket(8989);
????????System.out.println("-----------我是接收端------------");
????????//2.准备字节数组,打包 ????????byte[] arr = new byte[1024]; ????????DatagramPacket packet = new DatagramPacket(arr,arr.length); ????????//3.接收数据 ????????r.receive(packet); ????????//4.处理数据 ????????//byte[] getData() 返回数据缓冲区。 ????????//int getLength() 返回要发送的数据的长度或接收的数据的长度。 ????????byte[] newArr = packet.getData(); ????????int len = packet.getLength();
????????System.out.println(new String(newArr,0,len));
????????//5.关闭 ????????r.close(); ????} }
?客户端 ?Socket ????????Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号。 ????????InputStream getInputStream() ????????OutputStream getOutputStream() ????服务器 ?ServerSocket 该类实现服务器套接字。 ????????ServerSocket(int port) 创建绑定到指定端口的服务器套接字。 ????????Socket accept() 侦听对此套接字的连接并接受它。
????tcp协议下传输数据基于IO流
????tcp协议实现基本流程 : 客户端 ????????1.定义我是客户端-->指定要请求的服务器的IP+端口 ????????2.准备数据 ????????3.获取输出流 ????????4.输出-->IO操作 ????????5.刷出 ????????6.关闭 ?*/ public class Class001_Client { ????public static void main(String[] args) throws IOException { ????????System.out.println("-----------我是客户端--------------"); ????????// ?1.定义我是客户端-->指定要请求的服务器的IP+端口 ????????Socket client = new Socket("localhost",9999); ????????System.out.println("-----------与服务器端建立连接--------------"); ????????// ?2.准备数据 ????????String str = "你好"; ????????// ?3.获取输出流 ????????DataOutputStream os = new DataOutputStream(new BufferedOutputStream(client.getOutputStream())); ????????// ?4.输出-->IO操作 ????????os.writeUTF(str); ????????// ?5.刷出 ????????os.flush(); ????????// ?6.关闭 ????????os.close(); ????????client.close(); ????} }
tcp协议实现基本流程 : 服务端 ????????1.定义我是服务端 ????????2.阻塞式监听 ????????3.获取输入流-->接收客户端的请求数据 ????????4.处理数据 ????????5.关闭 ?*/ public class Class002_Server { ????public static void main(String[] args) throws IOException { ????????System.out.println("-----------我是服务器端-----------"); ????????// 1.定义我是服务端 ????????ServerSocket server = new ServerSocket(9999); ????????// 2.阻塞式监听 ????????Socket client = server.accept();
????????System.out.println("-----------一个客户端连接成功----------");
????????// 3.获取输入流-->接收客户端的请求数据 ????????DataInputStream is = new DataInputStream(new BufferedInputStream(client.getInputStream())); ????????String msg = is.readUTF(); ????????// 4.处理数据 ????????System.out.println(msg); ????????// 5.关闭 ????????is.close(); ????????client.close(); ????????server.close(); ????} }
tcp 单向登录: 客户端
1.定义客户端
2.准备数据(用户输入)
1)输入流
2)用户名与密码
3.获取输出流向服务器端发送数据(用户名与密码)
4.刷出
5.关闭
*/
public class Class003_LoginClient {
public static void main(String[] args) throws IOException {
System.out.println("-------我是客户端---------");
//1.定义客户端
Socket client = new Socket("localhost",9898);
//2.准备数据(用户输入)
// 1)输入流
BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
// 2)用户名与密码
System.out.println("请输入用户名");
String username = rd.readLine();
System.out.println("请输入密码");
String password = rd.readLine();
System.out.println(username+"-->"+password);
//3.获取输出流向服务器端发送数据(用户名与密码)
DataOutputStream os = new DataOutputStream(client.getOutputStream());
//username=laopei&password=1234
os.writeUTF("username="+username+"&password="+password);
//4.刷出
os.flush();
//5.关闭
os.close();
rd.close();
client.close();
}
}
tcp 单向登录: 服务端
1.定义我是服务器
2.阻塞式监听
3.获取输入流接收客户端发动的数据
4.处理数据
5.关闭
要求: 服务器端接收到用户输入的用户名与密码,与指定的laopei,1234比较是否相等,相等本地输出登录成功,不相等输出用户名或密码错误!!!
*/
public class Class003_LoginServer {
public static void main(String[] args) throws IOException {
System.out.println("--------我是服务器-------");
//1.定义我是服务器
ServerSocket server = new ServerSocket(9898);
//2.阻塞式监听
Socket client = server.accept();
System.out.println("一个客户端连接成功........");
//3.获取输入流接收客户端发动的数据
DataInputStream is = new DataInputStream(client.getInputStream());
String msg = is.readUTF(); //username=laopei&password=1234
//4.处理数据
System.out.println(msg);
//5.关闭
is.close();
client.close();
server.close();
}
}
tcp 双向登录: 客户端
1.定义客户端
2.准备数据(用户输入)
1)输入流
2)用户名与密码
3.获取输出流向服务器端发送数据(用户名与密码)
4.刷出
5.获取输入流 从服务器端读取响应
6.关闭
*/
public class Class005_LoginTwoWayClient {
public static void main(String[] args) throws IOException {
System.out.println("-------我是客户端---------");
//1.定义客户端
Socket client = new Socket("localhost",9898);
//2.准备数据(用户输入)
// 1)输入流
BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
// 2)用户名与密码
System.out.println("请输入用户名");
String username = rd.readLine();
System.out.println("请输入密码");
String password = rd.readLine();
System.out.println(username+"-->"+password);
//3.获取输出流向服务器端发送数据(用户名与密码)
DataOutputStream os = new DataOutputStream(client.getOutputStream());
//username=laopei&password=1234
os.writeUTF("username="+username+"&password="+password);
//4.刷出
os.flush();
//5.获取输入流 从服务器端读取响应
DataInputStream is = new DataInputStream(client.getInputStream());
System.out.println(is.readUTF());
//6.关闭
is.close();
os.close();
rd.close();
client.close();
}
}
tcp 双向登录: 服务端
1.定义我是服务器
2.阻塞式监听
3.获取输入流接收客户端发动的数据
4.处理数据
5.获取输出流 把结果响应 给客户端
6.刷出
7.关闭
要求: 服务器端接收到用户输入的用户名与密码,与指定的laopei,1234比较是否相等,相等本地输出登录成功,不相等输出用户名或密码错误!!!
*/
public class Class006_LoginTwoWayServer {
public static void main(String[] args) throws IOException {
System.out.println("--------我是服务器-------");
//1.定义我是服务器
ServerSocket server = new ServerSocket(9898);
//2.阻塞式监听
Socket client = server.accept();
System.out.println("一个客户端连接成功........");
//3.获取输入流接收客户端发动的数据
DataInputStream is = new DataInputStream(client.getInputStream());
String msg = is.readUTF(); //username=laopei&password=1234
//4.处理数据
System.out.println(msg);
//处理1)
/*String str = "username=laopei&password=1234";
if(str.equals(msg)){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}*/
//2)
String username = null;
String password = null;
String[] strs = msg.split("&");
for(String s:strs){
String[] arr = s.split("=");
if("username".equals(arr[0])){
username = arr[1];
}else if("password".equals(arr[0])){
password = arr[1];
}
}
//5.获取输出流 把结果响应 给客户端
DataOutputStream os = new DataOutputStream(client.getOutputStream());
if("laopei".equals(username) && "1234".equals(password)){
os.writeUTF("登录成功");
}else{
os.writeUTF("登录失败");
}
//6.刷出
os.flush();
//7.关闭
os.close();
is.close();
client.close();
server.close();
}
}
多用户登录服务器端
通过循环可以实现多用户登录
但是服务器只能排队对不同的客户端做响应
*/
public class Class007_MulLoginTwoWayServer {
public static void main(String[] args) throws IOException {
System.out.println("--------我是服务器-------");
//1.定义我是服务器
ServerSocket server = new ServerSocket(9898);
//2.阻塞式监听
boolean flag = true;
while(flag){
Socket client = server.accept();
System.out.println("一个客户端连接成功........");
//3.获取输入流接收客户端发动的数据
DataInputStream is = new DataInputStream(client.getInputStream());
String msg = is.readUTF();
//4.处理数据
String username = null;
String password = null;
String[] strs = msg.split("&");
for(String s:strs){
String[] arr = s.split("=");
if("username".equals(arr[0])){
username = arr[1];
}else if("password".equals(arr[0])){
password = arr[1];
}
}
//5.获取输出流 把结果响应 给客户端
DataOutputStream os = new DataOutputStream(client.getOutputStream());
if("laopei".equals(username) && "1234".equals(password)){
os.writeUTF("登录成功");
}else{
os.writeUTF("登录失败");
}
//6.刷出
os.flush();
//7.关闭
os.close();
is.close();
client.close();
}
server.close();
}
}
多用户登录服务器端
通过多线程实现
*/
public class Class008_MulLoginTwoWayServer {
public static void main(String[] args) throws IOException {
System.out.println("--------我是服务器-------");
//1.定义我是服务器
ServerSocket server = new ServerSocket(9898);
//2.阻塞式监听
boolean flag = true;
while(flag){
Socket client = server.accept();
System.out.println("一个客户端连接成功........");
//开启线程为上面监听到客户端响应
new Thread(new Channel(client)).start();
}
server.close();
}
static class Channel implements Runnable{
private Socket client = null;
private DataInputStream is = null;
private DataOutputStream os = null;
public Channel(Socket client) {
this.client = client;
try {
is = new DataInputStream(client.getInputStream());
os = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
//读入数据
public String read(){
String msg = null;
try {
msg = is.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
//写出
public void write(String msg){
try {
os.writeUTF(msg);
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭资源
public void close(){
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(client!=null){
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
//获取输入流接收客户端发动的数据
String msg = read();
//处理数据
String username = null;
String password = null;
String[] strs = msg.split("&");
for(String s:strs){
String[] arr = s.split("=");
if("username".equals(arr[0])){
username = arr[1];
}else if("password".equals(arr[0])){
password = arr[1];
}
}
//获取输出流 把结果响应 给客户端
if("laopei".equals(username) && "1234".equals(password)){
write("登录成功");
}else{
write("登录失败");
}
//关闭
close();
}
}
}
|