1.线程池的创建
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; //一个程序中只能有一个线程池 public class ThreadPoolDemo { public static void main(String[] args) { //public static ExecutorService newCachedThreadPool()创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。线程存活时间是60s ExecutorService threadPool = Executors.newCachedThreadPool(); //void execute(Runnable command)在未来某个时间执行给定的命令 Runnable command = new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"执行了"); } }; //threadPool.execute(command); //public static ExecutorService newSingleThreadExecutor()创建只有一个线程的线程池。如果线程不显示的关闭,线程将一直存活着 threadPool = Executors.newSingleThreadExecutor(); //threadPool.execute(command); //public static ExecutorService newFixedThreadPool(int nThreads)创建一个可重用固定线程数的线程池。如果线程不显示的关闭,线程将一直存活着 threadPool = Executors.newFixedThreadPool(1); //threadPool.execute(command); //threadPool.execute(command); //关闭线程池:void shutdown()启动一次顺序关闭,执行以前提交的任务,但不接受新任务 //threadPool.shutdown();//等整个程序退出的时候需要把线程池关闭 //new Thread(command).start();//我们自己创建线程 ThreadPoolUtils.execute(command);//pool-4-thread-1执行了 ThreadPoolUtils.shutdown(); ThreadPoolUtils.execute(command);//pool-5-thread-1执行了 } }
2.工具包 子类对象交由线程执行
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolUtils { private static ExecutorService threadPool = Executors.newCachedThreadPool(); /** * 将Runnable子类对象交由线程池执行 * * @param command */ public static void execute(Runnable command) { // 判断线程池是否被关闭 if (threadPool.isShutdown()) { // 如果线程池被关闭了,那么就新建一个线程池 threadPool = Executors.newCachedThreadPool(); execute(command);// 再次将任务交给线程池执行 } else { threadPool.execute(command); } } /** * 关闭线程池 */ public static void shutdown() { threadPool.shutdown(); } }
3.定时器的用法
import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; /* * Timer:一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。 * TimerTask:由 Timer 安排为一次执行或重复执行的任务。 */ public class TimerDemo { public static void main(String[] args) { test2(); } private static void test2() { //public Timer()创建一个新计时器。相关的线程不 作为守护程序运行 Timer timer = new Timer(); //protected TimerTask()创建一个新的计时器任务 TimerTask task = new TimerTask() { @Override public void run() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time = sdf.format(new Date()); System.out.println(time); } }; /* * public void schedule(TimerTask task, long delay, long period)安排指定的任务从指定的延迟后开始进行重复的固定延迟执行 参数: task - 所要安排的任务。 delay - 执行任务前的延迟时间,单位是毫秒。 period - 执行各后续任务之间的时间间隔,单位是毫秒。 */ timer.schedule(task, 0, 1000); } private static void test() { //public Timer()创建一个新计时器。相关的线程不 作为守护程序运行 Timer timer = new Timer(); //protected TimerTask()创建一个新的计时器任务 TimerTask task = new TimerTask() { @Override public void run() { System.out.println("定时器执行的任务"); } }; /* * public void schedule(TimerTask task,long delay)安排在指定延迟后执行指定的任务。 参数: * task - 所要安排的任务。 * delay - 执行任务前的延迟时间,单位是毫秒。 */ timer.schedule(task, 1000); //public boolean cancel()取消此计时器任务 //task.cancel();//终止的是任务 //public void cancel()终止此计时器,丢弃所有当前已安排的任务 timer.cancel();//终止此计时器 task = new TimerTask() { @Override public void run() { System.out.println("定时器执行的任务"); } }; timer.schedule(task, 1000); //一个定时器任务能不能被执行多次?不行的 //timer.schedule(task, 3000);//Task already scheduled or cancelled } //安排在指定延迟后执行指定的任务。 public void schedule(Runnable task,long delay){ //创建一个线程 new Thread(new Runnable() { @Override public void run() { //延迟指定delay的时间 try { Thread.sleep(delay); task.run();//run方法就执行在子线程中 } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } }
4.网络传输之UDP
server
import java.net.DatagramPacket; import java.net.DatagramSocket; //DatagramSocket:此类表示用来发送和接收数据包的套接字 public class Server { public static void main(String[] args) throws Exception { //1.创建Socket对象并监听指定的端口 DatagramSocket s = new DatagramSocket(8888); //2.创建一个数据包容器用于存储数据,udp一次传输的数据包最大是64k //public DatagramPacket(byte[] buf,int length) buf - 保存传入数据报的缓冲区。len - 要读取的字节数。 DatagramPacket p = new DatagramPacket(new byte[1024*64], 1024*64); //3.接收数据 //public void receive(DatagramPacket p)从此套接字接收数据包 s.receive(p); //4.拆开数据包,取出内容 //public byte[] getData()返回数据缓冲区 byte[] data = p.getData(); //public int getLength()返回将要发送或接收到的数据的长度 int len = p.getLength();//实际接收的字节个数 //将读取的内容转换成字符串 String content = new String(data,0,len); String ip = p.getAddress().getHostAddress(); System.out.println("ip="+ip+0+",内容="+content); //5.释放资源 s.close(); } }
client
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* * DatagramSocket:此类表示用来发送和接收数据包的套接字 * DatagramPacket:此类表示数据包 */ public class Client { public static void main(String[] args) throws Exception { //1.创建Socket对象 //public DatagramSocket()构造数据报套接字并将其绑定到本地主机上任何可用的端口 DatagramSocket s = new DatagramSocket(); //2.构建要发送的数据包,在数据包中指定要发送的内容,发送目标的ip地址,端口号 //public DatagramPacket(byte[] buf,int length,InetAddress address,int port)构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号 byte[] buf = "udp,我来了~".getBytes(); //包数据 int length = buf.length;//包长度 InetAddress address = InetAddress.getByName("192.168.3.54");//目的地址。 int port = 8888;//port DatagramPacket p = new DatagramPacket(buf, length, address, port); //3.发送数据包到服务端 //public void send(DatagramPacket p)从此套接字发送数据包 s.send(p); //4.关闭资源 //public void close()关闭此数据报套接字。 s.close(); } }
5.网络传输之TCP
server
import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) throws Exception { //1.创建ServerSocket对象并监听指定的端口号 ServerSocket ss = new ServerSocket(8888); //2.接受客户端的连接请求 //public Socket accept()侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。 Socket s = ss.accept(); //3.获取字节读取流 InputStream in = s.getInputStream(); //4.读取数据 byte[] b = new byte[1024]; int len = in.read(b);//len是实际读取的字节个数 //把接收到的数据转换成字符串 String content = new String(b,0,len); String ip = s.getInetAddress().getHostAddress(); System.out.println("ip="+ip+",内容="+content); //5.关闭资源 s.close();//连接对象关闭 ss.close();//服务器关闭 } }client
import java.io.OutputStream; import java.net.Socket; public class Client { public static void main(String[] args) throws Exception { // 1.创建Socket对象并指定ip地址和端口号 Socket s = new Socket("192.168.3.54", 8888); // 2.获取字节输出流 OutputStream out = s.getOutputStream(); // 3.写出数据到服务端 out.write("tcp,我来了~".getBytes()); // 4.关闭资源 s.close(); } }
6.
服务器给客户端反馈内容
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; //服务器给客户端反馈内容 public class Server { public static void main(String[] args) throws Exception { // 1.创建ServerSocket对象并监听指定的端口号 ServerSocket ss = new ServerSocket(8888); // 2.接收客户的请求 Socket s = ss.accept(); // 3.将字节读取流包装成字符缓冲读取流 InputStream in = s.getInputStream(); InputStreamReader isr = new InputStreamReader(in); BufferedReader br = new BufferedReader(isr); // 4.读取内容 String result = br.readLine(); System.out.println(result); // 5.反馈结果给客户端,将字节输出流包装成字符缓冲输出流 OutputStream out = s.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(out); BufferedWriter bw = new BufferedWriter(osw); // 6.将反馈结果返回给客户端 if (result.contains("钱")) { bw.write("我也很穷啊,没钱"); bw.newLine(); bw.flush(); } else { bw.write("我在啊,有啥事"); bw.newLine(); bw.flush(); } // 7.关闭资源 s.close(); ss.close(); } }
client
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; public class Client { public static void main(String[] args) throws Exception { // 1.创建Socket对象并指定ip地址和端口号 Socket s = new Socket("192.168.3.54", 8888); // 2.将获取的字节输出流包装成字符缓冲输出流 OutputStream out = s.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(out); BufferedWriter bw = new BufferedWriter(osw); // 3.写出数据 bw.write("在吗?借点钱花花"); bw.newLine(); bw.flush(); // 4.获取服务端的返回消息,将字节读取流包装成字符缓冲读取流 InputStream in = s.getInputStream(); InputStreamReader isr = new InputStreamReader(in); BufferedReader br = new BufferedReader(isr); String result = br.readLine(); System.out.println(result); // 5.关闭资源 s.close(); } }
7.
客户端键盘录入内容,服务器输出到控制台
import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; //客户端键盘录入内容,服务器输出到控制台 public class Server { public static void main(String[] args) throws Exception { // 1.创建ServerSocket对象并监听指定的端口号 ServerSocket ss = new ServerSocket(8888); // 2.接受客户端的请求 while (true) {// 可以一直接受客户端的请求 Socket s = ss.accept();//阻塞式 // 3.将字节读取流包装成字符缓冲读取流 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); String line;// 用于保存每次读取的内容 while ((line = br.readLine()) != null) { System.out.println(line); } // 4.关闭请求资源 s.close(); } } }
client
import java.io.BufferedWriter; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.Scanner; //客户端键盘录入内容,服务器输出到控制台 public class Client { public static void main(String[] args) throws Exception { // 1.创建Socket对象并指定ip地址和端口号 Socket s = new Socket("192.168.3.54", 8888); // 2.将字节输出流包装成字符缓冲输出流 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); // 3.键盘录入数据,输出到服务端 Scanner sc = new Scanner(System.in); while (true) { String content = sc.nextLine(); if (content.equals("886")) { break; } // 4.写出内容到服务端 bw.write(content); bw.newLine(); bw.flush(); } // 5.关闭资源 s.close(); } }
8.客户端上传文件,服务器端保存起来
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import java.net.Socket; //客户端上传文件,服务端保存起来 public class UploadClient { public static void main(String[] args) throws Exception { // 1.创建Socket对象并指定ip地址和端口号 Socket s = new Socket("192.168.3.54", 8888); // 2.因为上传的文件类型不确定,所以将字节输出流包装成字节缓冲输出流 BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream()); // 3.将要上传的文件封装到字节缓冲读取流中 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:/悟空.jpg")); // 4.循环的读写 byte[] buf = new byte[1024]; int len; while ((len = bis.read(buf)) != -1) { bos.write(buf, 0, len); } // 5.将数据刷新到服务端并且告诉服务端数据发送完毕 bos.flush(); s.shutdownOutput();//禁用此套接字的输出流 // 6.接收服务端的返回结果,将字节读取流包装成字符缓冲读取流 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); System.out.println(br.readLine()); // 7.关闭资源 bis.close();// 自己创建的资源 s.close(); } }
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.UUID; public class UploadServer { public static void main(String[] args) throws Exception { // 1.创建ServerSocket对象并监听指定的端口号 ServerSocket ss = new ServerSocket(8888); // 2.接收客户端请求连接 while (true) {// 一直接收客户端的请求 Socket s = ss.accept(); // 3.将字节读取流包装成字节缓冲读取流 BufferedInputStream bis = new BufferedInputStream(s.getInputStream()); // 4.将要保存的字节数据写出到一个文件中,创建字节缓冲输出流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/" + getUUID() + ".jpg")); // 5.循环读写 byte[] buf = new byte[1024]; int len; while ((len = bis.read(buf)) != -1) { bos.write(buf, 0, len); } // 6.将数据刷新到硬盘 bos.flush(); // 7.将上传结果返回给客户端,将字节输出流封装成字符缓冲输出流 System.out.println("上传文件成功"); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); bw.write("上传文件成功"); bw.newLine(); bw.flush(); // 8.关闭资源 bos.close();//自己创建的资源关闭 s.close();//请求对象关闭 } } public static String getUUID() { return UUID.randomUUID().toString().replaceAll("-", ""); } }
9.
server
import java.net.ServerSocket; import java.net.Socket; public class UploadServer { public static void main(String[] args) throws Exception { // 1.创建ServerSocket对象并监听指定的端口号 ServerSocket ss = new ServerSocket(8888); // 2.接收客户端请求连接 while (true) {// 一直接收客户端的请求 Socket s = ss.accept(); //接收到请求任务之后,将任务交给子线程来处理,因为可能有多个请求,所以需要启动多个子线程,所以使用线程池比较合理 ThreadPoolUtils.execute(new ServerRunnable(s)); } } }client
//客户端上传文件,服务端保存起来 public class UploadClient { public static void main(String[] args) throws Exception { ThreadPoolUtils.execute(new ClientRunnable("192.168.3.54", 8888, "E:/修仙.txt")); ThreadPoolUtils.execute(new ClientRunnable("192.168.3.54", 8888, "E:/修仙.txt")); ThreadPoolUtils.execute(new ClientRunnable("192.168.3.54", 8888, "E:/修仙.txt")); ThreadPoolUtils.execute(new ClientRunnable("192.168.3.54", 8888, "E:/修仙.txt")); } }
ServerRunnable
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.UUID; public class ServerRunnable implements Runnable { private Socket s; public ServerRunnable(Socket s) { super(); this.s = s; } @Override public void run() { try { // 3.将字节读取流包装成字节缓冲读取流 BufferedInputStream bis = new BufferedInputStream(s.getInputStream()); // 4.将要保存的字节数据写出到一个文件中,创建字节缓冲输出流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/" + getUUID() + ".txt")); // 5.循环读写 byte[] buf = new byte[1024]; int len; while ((len = bis.read(buf)) != -1) { bos.write(buf, 0, len); } // 6.将数据刷新到硬盘 bos.flush(); // 7.将上传结果返回给客户端,将字节输出流封装成字符缓冲输出流 System.out.println("上传文件成功"); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); bw.write("上传文件成功"); bw.newLine(); bw.flush(); // 8.关闭资源 bos.close();// 自己创建的资源关闭 } catch (Exception e) { e.printStackTrace(); } finally { if (null != s) { try { s.close(); } catch (IOException e) { e.printStackTrace(); } // 请求对象关闭 } } } public static String getUUID() { return UUID.randomUUID().toString().replaceAll("-", ""); } }ThreadPoolUtils
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolUtils { private static ExecutorService threadPool = Executors.newCachedThreadPool(); public static void execute(Runnable command) { threadPool.execute(command); } }ClientRunnable
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import java.net.Socket; public class ClientRunnable implements Runnable { private String ip; private int port; private String uploadPath; public ClientRunnable(String ip, int port, String uploadPath) { super(); this.ip = ip; this.port = port; this.uploadPath = uploadPath; } @Override public void run() { try (// 1.创建Socket对象并指定ip地址和端口号 Socket s = new Socket(ip, port); // 3.将要上传的文件封装到字节缓冲读取流中 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(uploadPath));) { // 2.因为上传的文件类型不确定,所以将字节输出流包装成字节缓冲输出流 BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream()); // 4.循环的读写 byte[] buf = new byte[1024]; int len; while ((len = bis.read(buf)) != -1) { bos.write(buf, 0, len); } // 5.将数据刷新到服务端并且告诉服务端数据发送完毕 bos.flush(); s.shutdownOutput();// 禁用此套接字的输出流 // 6.接收服务端的返回结果,将字节读取流包装成字符缓冲读取流 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); System.out.println(br.readLine()); } catch (Exception e) { e.printStackTrace(); } } }
inetAddressDemo
import java.net.InetAddress; public class InetAddressDemo { public static void main(String[] args) throws Exception { //public static InetAddress getByName(String host)在给定主机名的情况下确定主机的 IP 地址。 InetAddress inetAddress = InetAddress.getByName("www.taobao.cn"); //public String getHostAddress()返回 IP 地址字符串(以文本表现形式)。 String ip = inetAddress.getHostAddress(); System.out.println(ip);//192.168.3.106 //public String getHostName()获取此 IP 地址的主机名。 String hostName = inetAddress.getHostName(); System.out.println(hostName);//LENOVO-PC //public static InetAddress getLocalHost()返回本地主机 InetAddress localHost = InetAddress.getLocalHost(); System.out.println(localHost.getHostAddress());//192.168.200.1 System.out.println(localHost.getHostName());//DESKTOP-NT06AQ5 } }
10.聊天室
client
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.util.Scanner; public class Client { public static void main(String[] args) throws Exception { // 1.创建Socket对象 DatagramSocket s = new DatagramSocket(); // 2.构建数据包,内容应该是键盘录入 Scanner sc = new Scanner(System.in); byte[] bytes; DatagramPacket p; while (true) { String content = sc.nextLine(); // 如果用户输入886就表示结束输入 if (content.equals("886")) { break; } bytes = content.getBytes(); p = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.3.255"), 8888); // 3.发送数据包 s.send(p); } // 3.关闭资源 s.close(); } }
ClientRunnable
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.util.Scanner; public class ClientRunnable implements Runnable { private String ip; private int port; public ClientRunnable(String ip, int port) { super(); this.ip = ip; this.port = port; } @Override public void run() { try (// 1.创建Socket对象 DatagramSocket s = new DatagramSocket();) { // 2.构建数据包,内容应该是键盘录入 Scanner sc = new Scanner(System.in); byte[] bytes; DatagramPacket p; while (true) { String content = sc.nextLine(); // 如果用户输入886就表示结束输入 if (content.equals("886")) { break; } bytes = content.getBytes(); p = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(ip), port); // 3.发送数据包 s.send(p); } } catch (Exception e) { e.printStackTrace(); } } }
chatroom
public class ChatRoom { public static void main(String[] args) { ServerRunnable serverRunnable = new ServerRunnable(8888); ClientRunnable clientRunnable = new ClientRunnable("192.168.3.255", 8888); ThreadPoolUtils.execute(serverRunnable); ThreadPoolUtils.execute(clientRunnable); } }
server
import java.net.DatagramPacket; import java.net.DatagramSocket; public class Server { public static void main(String[] args) throws Exception { // 1.创建Socket对象并监听指定的端口号 DatagramSocket s = new DatagramSocket(8888); // 2.创建存放数据的数据包 DatagramPacket p = new DatagramPacket(new byte[1024 * 64], 1024 * 64); // 3.循环的接收数据 byte[] data; int len; String content; String ip; while (true) { s.receive(p); // 4.从包中取出内容 data = p.getData();// 获取缓冲区 len = p.getLength();// 获取实际的字节个数 // 把接收的字节变成字符串 content = new String(data, 0, len); ip = p.getAddress().getHostAddress(); System.out.println("ip=" + ip + ",内容=" + content); } } }
ServerRunnable
import java.net.DatagramPacket; import java.net.DatagramSocket; public class ServerRunnable implements Runnable { private int port; public ServerRunnable(int port) { super(); this.port = port; } @Override public void run() { try (// 1.创建Socket对象并监听指定的端口号 DatagramSocket s = new DatagramSocket(port);) { // 2.创建存放数据的数据包 DatagramPacket p = new DatagramPacket(new byte[1024 * 64], 1024 * 64); // 3.循环的接收数据 byte[] data; int len; String content; String ip; while (true) { s.receive(p); // 4.从包中取出内容 data = p.getData();// 获取缓冲区 len = p.getLength();// 获取实际的字节个数 // 把接收的字节变成字符串 content = new String(data, 0, len); ip = p.getAddress().getHostAddress(); System.out.println("ip=" + ip + ",内容=" + content); } } catch (Exception e) { e.printStackTrace(); } } }
ThreadPoolUtils
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolUtils { private static ExecutorService threadPool = Executors.newCachedThreadPool(); public static void execute(Runnable command) { threadPool.execute(command); } }CS和BS结构介绍
TCP传输图解
广播地址图解
计算机网路图解
网络模型介绍
网络通信三要素
线程池图解