线程池
1.线程池的作用:减少创建线程对象和销毁线程对象的时间,从而提高线程对象使用效率.
2.线程池:存放多个线程对象容器.
3.线程池常用接口和类
3.1:ExecutorService:线程池接口
常用方法:
shutdown()关闭线程池
submit(Runnable task) 从线程池中拿出一个线程对象来执行任务
3.2:Executors:线程池工具类对象
常用方法:
3.2.1:newCachedThreadPool();创建一个可缓存的线程池,可随机创建线程对象,线 程对象在1min内可以循环使用,如果1min内无任务执行,就会 自动回收这个线程对象.
3.2.2:newSingleThreadExecutor();创建只有一个线程对象的线程池.
3.2.3:newFixedThreadPool(int nThreads);创建指定线程数量的固定大小线程池
3.3:线程池的使用:
eg:public static void main(String[] args) {
//创建单个线程的线程池对象
//ExecutorService pool1= Executors.newSingleThreadExecutor();
//创建固定大小线程的线程池对象
//ExecutorService pool1=Executors.newFixedThreadPool(2);
//创建可缓存的线程池
ExecutorService pool1=Executors.newCachedThreadPool();
//创建一个任务对象
MyRunnable r1=new MyRunnable();
MyRunnable r2=new MyRunnable();
MyRunnable r3=new MyRunnable();
//从线程池中取出一个线程对象来执行任务
pool1.submit(r1);
pool1.submit(r2);
pool1.submit(r3);
//关闭线程池
pool1.shutdown();
}
网络编程
1.计算机网络:将分布在不同区域不同地方的多台计算机和网络设备通过线程连接起来组成一套大型系统,来实现计算机之间的信息传递和资源共享的设备.
2.网络编程:编写一个程序来实现网络间信息传递.
网络编程要使用的技术:网络编程+多线程+流
3.网络编程三要素:
3.1:IP:ip地址是每台计算机在网络中唯一标识.在同一个网络中不能有相同ip地址.
在不同网络中,可以有相同ip地址.
本机回环地址:127.0.0.1
查看本机IP:运行->cmd->ipconfig
查看本机是否能与其他计算机连通:运行->cmd->ping ip地址
3.2:端口:应用程序在网络中唯一标识.端口范围:0~65535,其中0-1024之间商品被系统软件占用.
3.3:协议:实现网络间通信的规则.
4.OSI七层模型和TCP/IP四层模型
5.InetAddress:此类表示Internet协议(IP)地址。
public static void main(String[] args) throws UnknownHostException {
//获得本机ip地址对象
// InetAddress ip1=InetAddress.getLocalHost();
InetAddress ip1=InetAddress.getByName("192.168.2.113");
System.out.println("本机ip:"+ip1.getHostAddress());
System.out.println("主机名:"+ip1.getHostName());
InetAddress[] ips=InetAddress.getAllByName("www.baidu.com");
for (InetAddress ip2:ips) {
System.out.println("百度ip:" + ip2.getHostAddress());
}
}
6.TCP网络编程:用的TCP协议.
TCP协议:是一种安全的,面向链接的网络层协议.优点:安全性高(因TCP的客户端与服务器端要经过三次握手才能建立连接,连接后才能互发消息).缺点:效率低.
Socket:客户端套接字(也称为“套接字”)。 套接字是两台机器之间通讯的信使.
ServerSocket:服务器套接字.监听客户端的套接字对象.
6.1:客户端发送消息,服务端接收消息
eg:public static void main(String[] args) throws IOException {
//创建套接字对象,第一个参数是服务端IP,第二个参数服务端应用的端口号
Socket socket1=new Socket("127.0.0.1",6666);
//用套接字对象创建网络输出字节流对象
OutputStream os=socket1.getOutputStream();
//声明一个变量存发送给服务器的消息
String word1="Hello Server!!";
//用网络输出流对象将消息通过网络发给服务器
os.write(word1.getBytes());
System.out.println("客户端发消息给服务器为:"+word1);
//关对象
os.close();
socket1.close();
}
public static void main(String[] args) throws IOException {
//创建服务器套接字对象
ServerSocket ss=new ServerSocket(6666);
System.out.println("客户端与服务器正在连接中...");
//用服务器套接字对象调用方法监听客户端Socket对象,并声明变量接收客户端Socket
Socket socket2=ss.accept();//接收到客户端的Socket对象,就表示客户端与服务器端三次握手成功,建立连接
System.out.println("客户端与服务器连接成功!");
//用套接字对象获得网络字节读取流
InputStream is=socket2.getInputStream();
//准备一个数组
byte[] b=new byte[1024];
//用网络字节读取流对象调用方法接收客户端的消息,返回的是消息的长度,消息的内容存在数组中
int len=is.read(b);
//将接收客户端的消息,转换为字符串类型
String recieveWord1=new String(b,0,len);
System.out.println("服务器接收客户端的消息为:"+recieveWord1);
//关闭对象
is.close();
ss.close();
}
6.2:客户端发送消息,服务端回复消息,完成一次聊天
eg:public static void main(String[] args) throws IOException {
//创建套接字对象,第一个参数是服务端IP,第二个参数服务端应用的端口号
Socket socket1=new Socket("127.0.0.1",6666);
//用套接字对象创建网络输出和输入字节流对象
OutputStream os=socket1.getOutputStream();
InputStream is=socket1.getInputStream();
/*客户端发消息给服务器端*/
//声明一个变量存发送给服务器的消息
String word1="Hello Server!!";
//用网络输出流对象将消息通过网络发给服务器
os.write(word1.getBytes());
System.out.println("客户端发消息给服务器为:"+word1);
/*客户端接收服务器回复的消息*/
//声明一个数组
byte[] b=new byte[1024];
//接收服务器的消息
int len=is.read(b);
//将接收回复的消息转换为字符串
String s2=new String(b,0,len);
System.out.println("客户端接收服务器回复消息为:"+s2);
//关对象
os.close();
socket1.close();
}
public static void main(String[] args) throws IOException {
//创建服务器套接字对象
ServerSocket ss=new ServerSocket(6666);
System.out.println("客户端与服务器正在连接中...");
//用服务器套接字对象调用方法监听客户端Socket对象,并声明变量接收客户端Socket
Socket socket2=ss.accept();//接收到客户端的Socket对象,就表示客户端与服务器端三次握手成功,建立连接
System.out.println("客户端与服务器连接成功!");
//用套接字对象获得网络字节读取和写入流
InputStream is=socket2.getInputStream();
OutputStream os=socket2.getOutputStream();
/*读取客户端的消息*/
//准备一个数组
byte[] b=new byte[1024];
//用网络字节读取流对象调用方法接收客户端的消息,返回的是消息的长度,消息的内容存在数组中
int len=is.read(b);
//将接收客户端的消息,转换为字符串类型
String recieveWord1=new String(b,0,len);
System.out.println("服务器接收客户端的消息为:"+recieveWord1);
/*服务器端回复消息给客户端*/
//声明一个变量存发送给服务器的消息
String word1="Hello Client!!";
//用网络输出流对象将消息通过网络发给服务器
os.write(word1.getBytes());
System.out.println("服务器端回复消息给客户端为:"+word1);
//关闭对象
is.close();
ss.close();
}
6.3:客户端与服务器端一对一循环聊天
eg:public static void main(String[] args) throws IOException {
//创建socket对象
Socket socket1=new Socket("127.0.0.1",7777);
//创建网络字符输出和输入流
BufferedWriter w=new BufferedWriter(new OutputStreamWriter(socket1.getOutputStream()));
BufferedReader r=new BufferedReader(new InputStreamReader(socket1.getInputStream()));
Scanner input=new Scanner(System.in);
//循环聊天
while (true){
/*发消息*/
//从键盘上接收要发送的消息
System.out.println("客户端发送给服务器的消息为:");
String sendMess=input.nextLine();
//将消息发送给服务器
w.write(sendMess);
//换行
w.newLine();
//刷新缓存
w.flush();
/*接收服务器消息*/
String recieveMess=r.readLine();
System.out.println("客户端接收服务器的消息为:"+recieveMess);
//约定一个结束语来结束聊天
if (sendMess.equals("886")||recieveMess.equals("886")){
break;
}
}
//关对象
socket1.close();
}
public static void main(String[] args) throws IOException {
//创建服务器的socket
ServerSocket ss=new ServerSocket(7777);
System.out.println("客户端与服务器正在连接中...");
//监视客户端,并接收客户端的socket
Socket socket1=ss.accept();
System.out.println("客户端与服务器连接成功!");
//创建网络字符输入和输出流
BufferedWriter w=new BufferedWriter(new OutputStreamWriter(socket1.getOutputStream()));
BufferedReader r=new BufferedReader(new InputStreamReader(socket1.getInputStream()));
Scanner input=new Scanner(System.in);
while (true){
/*接收客户端消息*/
String recieveMess2=r.readLine();
System.out.println("服务器接收客户端的消息为:"+recieveMess2);
/*回复客户端的消息*/
//从键盘上接收服务回复给客户端的消息
System.out.println("服务器回复客户端的消息为:");
String sendMess2=input.nextLine();
//将消息发送给客户端
w.write(sendMess2);
//换行
w.newLine();
//刷新
w.flush();
//约定一个结束语来结束聊天
if (sendMess2.equals("886")||recieveMess2.equals("886")){
break;
}
}
//关对象
ss.close();
}
6.4:用TCP实现文件上传
eg:public static void main(String[] args) throws IOException {
//创建客户端socket
Socket socket2=new Socket("127.0.0.1",8888);
//上传的文件
File f1=new File("C:\\Users\\sx\\Desktop\\image\\d.jpg");
//创建本地读取流
InputStream is=new FileInputStream(f1);
//创建网络写入流
OutputStream os=socket2.getOutputStream();
/*先先本地硬盘上的文件读取到程序中再写入到服务器,边读取边写入*/
//1,先将文件名发送到服务器端
os.write(f1.getName().getBytes());
//2.将文件内容发送到服务器
//准备一个数组
byte[] b=new byte[1024];
//边读取本地文件边写入服务器
int len;
while ((len=is.read(b))!=-1){
os.write(b,0,len);
}
System.out.println("上传成功");
//3.关对象
is.close();
os.close();
socket2.close();
}
public static void main(String[] args) throws IOException {
//创建服务器的socket
ServerSocket ss=new ServerSocket(8888);
System.out.println("客户端与服务器正常连接中...");
//监视客户端,并接收客户端的socket
Socket socket2=ss.accept();
System.out.println("客户端与服务器连接成功");
//创建网络读取流
InputStream is=socket2.getInputStream();
/*先读取原文件名*/
//准备一个数组
byte[] b=new byte[1024];
//1.第一次读取文件名,将读取的内容存在数组中,返回的是读取的长度
int len=is.read(b);
String fileName=new String(b,0,len);
//创建本地写入流
OutputStream os=new FileOutputStream("Day34\\aa\\"+fileName);
//将读取的图片内容写入到服务器硬盘上,边读取边写入
int len2;
while ((len2=is.read(b))!=-1){
os.write(b,0,len2);
}
System.out.println("上传成功");
//关对象
is.close();
os.close();
ss.close();
}
7.UDP编程:用udp协议.
udp协议:是一种不安全,无需建立连接的传输效率高的协议.UDP传输数据时是有大小限制 的,每个被传输的数据报必须限定在64KB之内.udp没有服务器端,都是客户端.
DatagramSocket:此类表示用于发送和接收数据报数据包的套接字。(两个网络传消息的信使) .
DatagramPacket:该类表示数据报包。
7.1:客户端1发送的接收一次客户端2的消息
eg:public static void main(String[] args) throws Exception {
//创建socket对象,参数是当前这个客户端的端口号
DatagramSocket socket1=new DatagramSocket(1111);
/*客户端1发送消息给客户端2*/
//准备要发送的消息
byte[] b="恭喜你中了好声音第一等奖".getBytes();
//将要发送的消息打成数据发送包,第一个参数要发送的数据,第二个数据的长度,第三个是接收方IP对象,第四个是接收方的端口号
DatagramPacket packet1=new DatagramPacket(b,b.length, InetAddress.getByName("127.0.0.1"),2222);
//用socket发送数据包
socket1.send(packet1);
System.out.println(socket1.getLocalPort()+"发送给"+packet1.getPort()+"的消息为:"+new String(b));
/*客户端1接收客户端2回复的消息*/
//准备一个数组
byte[] b2=new byte[1024];
//构造一个接收包
DatagramPacket packet2=new DatagramPacket(b2,b2.length);
//用socket接收数据包
socket1.receive(packet2);
//获得接收的数据
String recieveMess=new String(packet2.getData(),0,packet2.getLength());
System.out.println(socket1.getLocalPort()+"接收"+packet2.getPort()+"消息为:"+recieveMess);
//关对象
socket1.close();
}
public static void main(String[] args) throws Exception {
//创建socket对象,参数是当前客户端的端口号
DatagramSocket socket2=new DatagramSocket(2222);
/*客户端2接收客户端1的消息*/
//准备一个数组
byte[] b=new byte[1024];
//构造一个数据接收包
DatagramPacket packet3=new DatagramPacket(b,b.length);
//用socket接收数据
socket2.receive(packet3);
//获得接收的数据
String recieveMess=new String(packet3.getData(),0,packet3.getLength());
System.out.println(socket2.getLocalPort()+"接收"+packet3.getPort()+"消息为:"+recieveMess);
/*客户端2回复客户端1的消息*/
//准备要回复(发送)的消息
byte[] sendMess="到哪里去领奖?".getBytes();
//将消息封装数据发送包
DatagramPacket packet4=new DatagramPacket(sendMess,sendMess.length, InetAddress.getByName("127.0.0.1"),1111);
//用socket将消息发送给客户端1
socket2.send(packet4);
System.out.println(socket2.getLocalPort()+"回复"+packet4.getPort()+"消息为:"+new String(sendMess));
//关流
socket2.close();
}
7.2:客户端1发送的接收一次客户端2的消息
eg:/**
*发送消息的线程
* @version 1.0
* @auth sx
* @date 2020/3/26
*/
public class SendThread extends Thread {
//声明发送方的socket对象
DatagramSocket socket1;
//声明接收方ip对象
InetAddress ip2;
//声明接收方端口
int port2;
/**
* 通过构造方法将发送方的socket,接收方ip对象,接收方端口
*
* @param socket1,
* @param ip2
* @param port2
*/
public SendThread(DatagramSocket socket1, InetAddress ip2, int port2) {
this.socket1 = socket1;
this.ip2 = ip2;
this.port2 = port2;
}
@Override
public void run() {
Scanner input = new Scanner(System.in);
try {
while (true) {
//准备要发送的消息
byte[] b = input.next().getBytes();
//将要发送的消息打成数据发送包,第一个参数要发送的数据,第二个数据的长度,第三个是接收方IP对象,第四个是接收方的端口号
DatagramPacket packet1 = new DatagramPacket(b, b.length, ip2, port2);
//用socket发送数据包
socket1.send(packet1);
System.out.println(socket1.getLocalPort() + "发送给" + packet1.getPort() + "的消息为:" + new String(b));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
*接收线程
* @version 1.0
* @auth sx
* @date 2020/3/26
*/
public class RecieveThread extends Thread{
//声明接收方的socket
DatagramSocket socket2;
/**
*用构造方法传入接收方的socket
*@param socket2
*@return
*/
public RecieveThread(DatagramSocket socket2) {
this.socket2 = socket2;
}
@Override
public void run() {
try {
while (true) {
//准备一个数组
byte[] b2 = new byte[1024];
//构造一个接收包
DatagramPacket packet2 = new DatagramPacket(b2, b2.length);
//用socket接收数据包
socket2.receive(packet2);
//获得接收的数据
String recieveMess = new String(packet2.getData(), 0, packet2.getLength());
System.out.println(socket2.getLocalPort() + "接收" + packet2.getPort() + "消息为:" + recieveMess);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
//创建socket对象,参数是当前这个客户端的端口号
DatagramSocket socket1=new DatagramSocket(1111);
//创建发送消息的线程和接收消息的线程
SendThread s=new SendThread(socket1, InetAddress.getLocalHost(),2222);
RecieveThread r=new RecieveThread(socket1);
//启动线程
r.start();
s.start();
}
public static void main(String[] args) throws Exception {
//创建socket对象,参数是当前客户端的端口号
DatagramSocket socket2=new DatagramSocket(2222);
//创建发送消息的线程和接收消息的线程
SendThread s=new SendThread(socket2, InetAddress.getLocalHost(),1111);
RecieveThread r=new RecieveThread(socket2);
//启动线程
r.start();
s.start();
}