一、线程一些常用方法的讲解
1.setDaemon()---设置某个线程为守护线程
package com.bianyiit.cast;
public class XianChenTuoZhanDemo1 {
public static void main(String[] args) {
ShouHu sh = new ShouHu();
sh.setName("守护线程");
//将sh设置成守护线程
sh.setDaemon(true);
//还是交叉执行
sh.start();
//守护线程
for (int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+i);
if(i>500){
break;
//随着被守护的线程结束,守护线程而跟着结束掉
}
}
//两个线程交叉执行
}
}
class ShouHu extends Thread{
@Override
public void run() {
int i=1;
while (true) {
//继承了Thread,可以直接用getName()
System.out.println(getName()+"守护线程启动了"+i);
i++;
if(i==1000){
break;
}
}
}
}
总结:随着被守护的线程结束,守护线程而跟着结束掉
2.join()---让当前线程一直处于运行状态(一直获取cpu的执行时间)
package com.bianyiit.cast;
public class JoinDemo2 {
public static void main(String[] args) throws InterruptedException {
Join join = new Join();
join.setName("join");
join.start();
//把线程设置为join线程,优先获取CPU的执行权
join.join();
//主线程
for (int i = 0; i < 500 ; i++) {
System.out.println(Thread.currentThread().getName()+"主线程"+i);
}
}
}
class Join extends Thread{
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println(getName()+"线程"+i);
}
}
}
注意:join线程全部执行完之后才执行主线程
3.setPriority(int newPriority)---设置线程的优先级
package com.bianyiit.cast;
public class PriorityDemo3 {
public static void main(String[] args) {
Priority p1 = new Priority();
Thread t1=new Thread(p1);
t1.setName("线程1");
t1.setPriority(Thread.MAX_PRIORITY); //最大优先级
Thread t2=new Thread(p1);
t2.setName("线程2");
t2.setPriority(Thread.MIN_PRIORITY); //最小优先级
Thread t3=new Thread(p1);
t3.setName("线程3");
t3.setPriority(Thread.NORM_PRIORITY); //默认优先级
t1.start();
t2.start();
t3.start();
//优先级高的线程获取CPU执行权的概率要比优先级低的线程大的多
//setPriority---设置线程的优先级
/*Thread.MAX_PRIORITY; //最大优先级10
Thread.MIN_PRIORITY; //最小优先级1
Thread.NORM_PRIORITY; //默认优先级5*/
}
}
class Priority implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}
}
注意:优先级高的线程获取CPU执行权的概率要比优先级低的线程大的多
4.在开发时,可以使用匿名内部类来完成线程的创建和启动
package com.bianyiit.cast;
public class NiMingNeiBuNeiDemo4 {
public static void main(String[] args) {
//三种使用匿名内部类启动线程的方式
/*new Thread(){
@Override
public void run() {
for (int i = 0; i <1000 ; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
}.start();*/
/*new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <1000 ; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
}).start();*/
Thread t=new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <1000 ; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
});
t.start();
}
}
5.Timer的对象.schedule()---定期重复执行某一个线程/步骤
package com.bianyiit.cast;
import java.util.Timer;
import java.util.TimerTask;
public class TimerDemo5 {
public static void main(String[] args) throws InterruptedException {
//工具,定期重复执行某一个线程/步骤----相当于就是一个定时器
//创建定时器对象
Timer t=new Timer();
/* //创建一个date对象--从1900年开始计算,月份要减一
Date date=new Date(119,10,28,10,17,40);
//定时某个任务执行的时间
t.schedule(new RenWu(),date,5000);
//TimerTask是一个抽象类,不能直接创建对象*/
for (int i = 5; i >0 ; i--) {
System.out.print(i+" ");
Thread.sleep(1000);
}
t.schedule(new RenWu(),0);
}
}
//创建一个任务类
class RenWu extends TimerTask {
//重写父类的抽象方法
@Override
public void run() {
System.out.println("Suprise MZ fuck!!");
}
}
注意:上述代码相当于一个定时器,定时时间到,启动线程,执行run()里面的代码
二、网络编程概述
1.什么是网络编程?就是通过网络进行数据的传输(设备与设备之间进行数据的传输)
2.##设备与设备(不一定是电脑)##如何进行数据的传输??遵循TCP和UDP协议
3.浏览器和服务器之间如何进行数据数据的传输??遵循http和https协议
1.OSI标准模型
OSI(Open System Interconnect),即开放式系统互联。 一般都叫OSI标准模型,是ISO(国际标准化组织)组织在1985年研究的网络互连模型。ISO为了更好的使网络应用更为普及,推出了OSI参考模型。其含义就是推荐所有公司使用这个规范来控制网络。这样所有公司都有相同的规范,就能互联了。
2.TCP/IP参考模型
在TCP/IP参考模型中,去掉了OSI参考模型中的会话层和表示层(这两层的功能被合并到应用层实现)。同时将OSI参考模型中的数据链路层和物理层合并为主机到数据链路层层
3.网络通信三要素:协议、IP地址和端口号
3.1 什么是协议:规定我们的具体操作(定义了规则/传输数据的一些方式)
具体的协议:http和https是浏览器与服务器之间的协议,而今天学的网络编程的协议是TCP和UDP是设备与设备之间的协议
3.2 IP地址:www.bianyiit.com(域名/IP地址)--127.0.0.1(点分十进制法)---代表的是电脑的地址
3.3 端口号:代表的是具体的应用程序的地址---默认是80,
IP地址是唯一的,端口号是可以重复的
3.4 计算机都有自己唯一的IP地址,计算机中每一个正在运行的程序都有一个端口号
IP地址分为两种:IPV4(四个字节/32位)和IPV6,都是0-255之间
IPV4最多能设置2的32次方个IP(40多亿个)
IPV6---2的128次方个
注意1:端口号取值范围0--65535 但是0-1023这些端口号已经被一些知名的应用程序占用了,所以建议大家使用1024之后的端口号
注意2:每个电脑都可以用127.0.0.1访问自己电脑,这个叫做本地回环地址
三、那么该如何进行数据的传输??
1.学习一个类InetAddress,它提供了一系列与IP地址相关的方法
2.InetAddress的常用方法
2.1 static InetAddress getByName(String host)---在给定主机名的情况下确定主机的 IP 地址
2.2 static InetAddress getLocalHost()---返回本地主机
2.3 String getHostName()---获取此 IP 地址的主机名
2.4 String getHostAddress()---返回 IP 地址字符串(以文本表现形式)
3.代码演示
package com.bianyiit.internet;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressDemo3 {
public static void main(String[] args) throws UnknownHostException {
InetAddress address1 =InetAddress.getLocalHost();
//返回IP地址的对象---主机名/IP地址
System.out.println(address1);
//返回IP地址的对象---主机名/IP地址
InetAddress byName = InetAddress.getByName("电脑的主机名");
System.out.println(byName);
//通过IP地址对象调用getHostName(),以字符串的方式返回的是主机名
String hostName = address1.getHostName();
System.out.println(hostName);
//通过IP地址对象调用getHostAddress(),以字符串的方式返回的是IP地址
String hostAddress = address1.getHostAddress();
System.out.println(hostAddress);
}
}
四、UDP协议
1.UDP协议解释
1.1 不安全协议(只管传输数据,不管数据是否真正的传了过去也不管对方是否完全接收了数据)
1.2 效率高(如果传输数据对数据的安全性不做要求,或者丢失数据不会产生太大的影响)选择使用UDP协议,否则就选择TCP协议
2.JDK中提供了一个DatagramSocket类,此类表示用来发送和接收数据报包的套接字。
//DatagramSocket用于发送的构造方法
2.1--DatagramSocket()---构造数据报套接字并将其绑定到本地主机上任何可用的端口。
//DatagramSocket用于发送的常用方法
2.2--void send(DatagramPacket p)----从此套接字发送数据报包。
//DatagramSocket用于接收的构造方法
2.3--DatagramSocket(int port)---创建数据报套接字并将其绑定到本地主机上的指定端口。
//DatagramSocket用于接收的常用方法
2.4--void receive(DatagramPacket p)---从此套接字接收数据报包。
3.JDK中提供了一个DatagramPacket类,用于封装UDP通信中发送或者接收的数据
//DatagramPacket用于发送的构造方法
3.1--DatagramPacket(byte[] buf, int length, InetAddress address, int port) ---构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
//DatagramPacket用于接收的构造方法
3.2--DatagramPacket(byte[] buf, int length)---构造 DatagramPacket,用来接收长度为 length 的数据包。
//DatagramPacket用于接收的常用方法
3.3--byte[] getData()---返回数据缓冲区。
3.4--int getLength()---返回将要发送或接收到的数据的长度。
3.5--int getPort()---返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。
3.6--InetAddress getAddress()---返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
//将接收到的字节数组转换成字符串的方法
3.7--String(byte[] bytes)---通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
3.8--String(byte[] bytes, int offset, int length)---通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。
4.UDP通信Java代码
package com.bianyiit.internet;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*UDP协议:发送端*/
public class SendDataSocketDemo5 {
public static void main(String[] args) throws IOException {
//发送和接收端都需要用到的一个套接字---DatagramSocket(类)
//第一步:创建发送端的连接对象
DatagramSocket ds = new DatagramSocket(); //不需要指定发送端的端口号,默认生成一个端口号
String s="hello world";
//需要把数据进行打包操作,首先要有一个数据包
DatagramPacket dp = new DatagramPacket(s.getBytes(),s.getBytes().length,InetAddress.getByName("127.0.0.1"),8888);
//发送数据
ds.send(dp);
//释放资源
ds.close();
}
}
package com.bianyiit.internet;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*UDP协议:接收端*/
public class ReceiveDataSocketDemo6 {
public static void main(String[] args) throws IOException {
//发送和接收端的一个套接字DatagramSocket(类)
//第一步:创建接收端的连接对象
DatagramSocket ds = new DatagramSocket(8888);//接收端要指定端口号
//定义一个字节数组
byte[] bytes=new byte[20];
//创建一个空的集装箱对象(数据包对象)----用来接收数据
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
ds.receive(dp); //这时会处于一种阻塞状态---等待发送端把数据发送过来
//发送过来的具体数据
byte[] data = dp.getData();
System.out.println(data);
//将字节数组转换成字符串
System.out.println(new String(data));
//发送过来的数据的具体长度
int length = dp.getLength();
System.out.println(length);
//返回发送端的端口号
int port = dp.getPort();
System.out.println(port);
/*String s = new String(data, 0, data.length);
System.out.println(s);*/
InetAddress address = dp.getAddress();
System.out.println(address);
}
}
5.使用UDP构建一个基本的网络聊天室
package com.bianyiit.udpchat;
//发送端1----接收端2
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class ClientDemo {
public static void main(String[] args) throws IOException {
while (true) {
Scanner sc=new Scanner(System.in);
//创建发送端的对象
DatagramSocket ds = new DatagramSocket();
System.out.print("发送端送:");
String s = sc.next();
//数据的打包
DatagramPacket dp = new DatagramPacket(s.getBytes(), s.getBytes().length, InetAddress.getByName("127.0.0.1"), 9999);
ds.send(dp);
ds.close();
//创建接收端链接对象
DatagramSocket ds1 = new DatagramSocket(8888);
//创建数据包接收数据
byte[] arr=new byte[50];
DatagramPacket dp1=new DatagramPacket(arr,arr.length);
//接收数据包
ds1.receive(dp1);
//将数据包拆开
byte[] data = dp1.getData();
String s1=new String(data);
System.out.println(s1);
ds1.close();
}
}
}
package com.bianyiit.udpchat;
//接收端1----发送端2
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class ServerDemo {
public static void main(String[] args) throws IOException {
while (true) {
DatagramSocket ds = new DatagramSocket(9999);
byte[] arr=new byte[50];
//创建数据包对象
DatagramPacket dp = new DatagramPacket(arr,arr.length);
//接收数据包
ds.receive(dp);
//将数据包拆开
byte[] data=dp.getData();
String s=new String(data);
System.out.println(s);
ds.close();
Scanner sc=new Scanner(System.in);
//创建发送端对象
DatagramSocket ds1 = new DatagramSocket();
System.out.println("服务器说:");
String s1 = sc.next();
//创建数据包对象
DatagramPacket dp1 = new DatagramPacket(s1.getBytes(),s1.getBytes().length, InetAddress.getLocalHost(),8888);
ds1.send(dp1);
ds1.close();
}
}
}
注意:UDP协议:发送端和接收端,同时UDP是通过数据包的方式发送数据
五、TCP协议
1.TCP协议解释
1.1 什么是TCP协议??---重点掌握
安全协议(要经过三次握手,确定对方完全接收数据)
效率要低点
1.2 简单解释什么是三次握手
A问B,在吗?? B回答我在,反过来问A你在吗?? A回答我在,这时可以进行数据的交互*/
1.3 UDP称为发送端和接收端,TCP和Http统称为客户端和服务端
1.4 TCP通过流的方式发送数据,通过Socket套接字建立客户端与服务器端的连接
1.5 通过ServerSocket建立服务器端与客户端之间的连接
2.JDK提供了一个Socket类,用于实现TCP客户端程序。
//Socket类的构造方法
2.1--Socket(InetAddress address, int port)---创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
//Socket类的常用方法
2.2--OutputStream getOutputStream()---返回此套接字的输出流。
//PrintWriter打印流的构造方法
2.3--PrintWriter(OutputStream out, boolean autoFlush)---通过现有的 OutputStream 创建新的 PrintWriter,自带刷新效果
//PrintWriter打印流的写入方法
2.4--void write(char[] buf)---写入字符数组。
2.5--void write(int c)---写入单个字符。
2.6--void write(String s)---写入字符串。
//OutputStream字节输出流的写入方法
2.7--void write(byte[] b)---将 b.length 个字节从指定的 byte 数组写入此输出流。
//OutputStreamWriter字节流转字符流的构造方法
2.8--OutputStreamWriter(OutputStream out)创建使用默认字符编码的 OutputStreamWriter。
//BufferedWriter高效字符输出流的构造方法
2.9--BufferedWriter(Writer out)---创建一个使用默认大小输出缓冲区的缓冲字符输出流。
//BufferedWriter高效字符输出流的常用方法
2.10-- void write(String s) 写入字符串。
2.11--void flush()---刷新此输出流并强制写出所有缓冲的输出字节。
3.JDK提供了一个ServerSocket类,用于实现服务器端的程序
//ServerSocket类的构造方法
3.1--ServerSocket(int port)---创建绑定到特定端口的服务器套接字。
//ServerSocket类的一个很重要的方法,进入监听状态----返回的是一个Socket对象
3.2--Socket accept()---侦听并接受到此套接字的连接。
//Socket类的一个很重要的方法,通过Socket对象调用该输入流方法获取从客户端传来的信息
3.3--InputStream getInputStream()---返回此套接字的输入流。
//InputStreamReader字节转字符的构造方法
3.4--InputStreamReader(InputStream in)---创建一个使用默认字符集的 InputStreamReader。
//BufferedReader高效字符输入流的构造方法
3.5--BufferedReader(Reader in)---创建一个使用默认大小输入缓冲区的缓冲字符输入流。
//BufferedReader高效字符输入流的常用方法
3.6--String readLine()---读取一个文本行。
4.TCP通信Java代码
package com.bianyiit.tcp;
//客户端通信代码
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class SocketDemo1 {
public static void main(String[] args) throws IOException {
//创建客户端与服务器端的连接对象
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
//传输数据??---需要用到流对象---字节输出流
//返回连接对象调用getOutputStream()---返回字节输出流对象
OutputStream os = socket.getOutputStream();
//把字节输出流转换成打印流
//因为参数设置为true时,打印流有一个自动刷新的效果,
PrintWriter pw=new PrintWriter(os,true);
String s1="hello树先生";
pw.write(s1);
//释放资源
pw.close();
socket.close();
}
}
package com.bianyiit.tcp;
//服务端通信代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketDemo1 {
public static void main(String[] args) throws IOException {
//创建服务器端和客户端的连接对象
ServerSocket serverSocket = new ServerSocket(9999);
//先要进入监听状态----返回的是一个Socket对象
Socket accept = serverSocket.accept();
//创建字节输入流对象,调用getInputStream()--返回的是InputStream对象
InputStream is = accept.getInputStream();
//把字节输入流转换成字符输入流
InputStreamReader isr = new InputStreamReader(is);
//将字符转换流转换成高效流
BufferedReader br = new BufferedReader(isr);
//读取数据
String s = br.readLine();
System.out.println(s);
}
}