当前位置: 首页 > news >正文

Java基础复习-下-多线程-网络编程-反射

多线程

实现方式

继承Thread

实现Runnable接口

实现Callable接口

成员方法-Thread

优先级

守护线程

举例:

线程1是非守护线程,线程2是守护线程。

当非守护线程执行结束时,线程2也就没必要存在了,系统会告诉线程2,你也要结束了。此时不管线程2是否执行完毕,都会停止当前的进度。但是,并不是线程1一停止,线程2立马结束,系统告诉线程2 让线程2结束的这一段时间,线程2还会执行。

礼让(出让)线程

当执行到Thread.yield()时,该线程会把cpu控制权交出去,然后重新抢夺cpu。当然,这个线程也可能会再次抢到cpu。

插入线程

线程的生命周期

jdk5.0以后的生命周期发生了变化。

线程安全问题

同步代码块

使用同步代码块将需要顺序执行的地方锁起来。

同步方法

用方法以继承Thread使用同步代码块,自己指定锁对象

用后面的实现Runnable接口的,可以使用同步方法,因为锁对象默认是this。也就是左边的mr

Lock锁

死锁

线程1拿着A锁等B锁

线程2拿着B锁等A锁

两个线程都在等对方释放锁。互相等待。

等待唤醒机制(生产者和消费者)

Desk:

public class Desk {
//    桌子,控制生产者和消费者的执行
//    桌子上是否有食物,0没有食物,1有食物public static int foodFlag = 0;//    消费者总共可以吃几次食物public static int consumerCount = 10;//    锁对象public static Object lock = new Object();
}

Consumer:

public class Consumer extends Thread{@Overridepublic void run() {while (true){
//            锁监视器使用在Desk中创建的锁对象,为了后续生产者和消费者等待或唤醒synchronized (Desk.lock){if (Desk.consumerCount == 0){break;}else {
//                    判断桌子上是否有食物if(Desk.foodFlag == 0){
//                        没有食物,让绑定Desk.lock的线程进行等待try {Desk.lock.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}else {
//                        有食物Desk.consumerCount--;System.out.println("消费者开始吃食物了,还可以吃 ---> " + Desk.consumerCount + " --- 份食物");
//                        将桌子设置成没有食物的状态Desk.foodFlag = 0;
//                        唤醒绑定了Desk.lock这把锁的所有生产者Desk.lock.notifyAll();}}}}}
}

Producer:

public class Producer extends Thread{@Overridepublic void run() {while (true){synchronized (Desk.lock){
//                判断消费者是否还能吃食物if (Desk.consumerCount == 0){break;}else {
//                    首先判断桌子上是否有食物if (Desk.foodFlag == 1){
//                        桌子上已经有食物了try {Desk.lock.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}else {
//                        桌子上没有食物System.out.println("生产者开始生产食物了,当前生产第 " + Desk.consumerCount + " 份食物");
//                        将桌子设置成有食物的状态Desk.foodFlag = 1;
//                        唤醒Desk.lock这个锁监视器上绑定的其他等待的线程Desk.lock.notifyAll();}}}}}
}

测试:

public class Test {public static void main(String[] args) {Producer producer = new Producer();Consumer consumer = new Consumer();producer.setName("生产者");consumer.setName("消费者");producer.start();consumer.start();}
}

测试结果:

使用阻塞队列来实现消费者和生产者的消费等待机制:

队列:

这里的queue的put方法和take方法不需要加锁,因为他们的底层都用了lock锁,我们无需再次加锁

这样打印出来的结果可能会出现连续的问题。这不是代码问题,因为我们把打印的语句放到了锁的外面。因为他的底层加锁了,但我们没法在底层源码中加锁。

多线程的6种状态

Java中没有定义运行这种状态,因为线程抢占到cpu后,程序就交给操作系统去处理了,jvm就不管了,所以,jdk没有定义运行状态,这里为了方便理解,写了运行状态。 

线程栈:

例题:

测试类:

线程池

代码实现

创建没有上线的线程池(实际上是有上限的,int的最大数,电脑会先扛不住)

有上限的创建线程池

线程池的参数:

当核心线程全在处理任务,阻塞队列也排满了,临时线程也全部都在工作--线程池满负荷工作,那么再来其他任务,就会触发拒绝策略

拒绝策略:

public static void main(String[] args) {ThreadPoolExecutor pools = new ThreadPoolExecutor(3,6,60,TimeUnit.SECONDS,new ArrayBlockingQueue<>(3),// new LinkedBlockingQueue<>()new ThreadPoolExecutor.AbortPolicy());}

线程池参数设置问题:

后续资料可以看黑马Java课程下部的:juc额外扩展资料

网络编程

概念:

IP

IPv4

Ipv6

端口号

网络通信协议

InetAddress

UDP通信

UDP发送数据

UDP接收数据

通信案例

发送端:

接收端:

UDP的通信方式:

代码实现:

组播

发送端:

接收端:

广播

就是把地址改成255.255.255.255即可

TCP通信方式

代码实现:

发送端:

接收端:

这种字节流只能传输英文,传输中文会导致乱码问题

解决乱码问题:

在接收端,使用转换流,将字节流转成字符流,后续也可以继续使用缓存字符流来包装提升读取速度。

代码:

public class TcpTestWriter {
//    发送端public static void main(String[] args) throws IOException {Socket socket = new Socket("127.0.0.1",65535);BufferedWriter bos = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));bos.write("你好你好,Java");bos.close();socket.close();}
}
public class TcpTestReader {public static void main(String[] args) throws IOException {ServerSocket ss = new ServerSocket(65535);Socket socket = ss.accept();// 等待建立连接BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));int len;char[] c1 = new char[1024];while ((len = br.read(c1)) != -1){System.out.println(new String(c1,0,len));}br.close();socket.close();}
}

三次握手、四次挥手

双向读写数据

大作业:聊天室

源代码:

客户端:

public class Client {
//    用户端口
static ThreadPoolExecutor pool;static {pool = new ThreadPoolExecutor(3,6,60,TimeUnit.SECONDS,new ArrayBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());}public static void main(String[] args) throws IOException {Socket socket = new Socket("127.0.0.1",65535);
//        System.out.println("连接服务端成功");Scanner scanner = new Scanner(System.in);System.out.println("---欢迎来到星河网络聊天室---");while (true){System.out.println("1、登录!");System.out.println("2、注册!");System.out.println("请输入要执行的操作:");String choose = scanner.nextLine();switch (choose){case "1" -> login(socket);case "2" -> System.out.println("注册");}}}private static void login(Socket socket) throws IOException {Scanner scanner = new Scanner(System.in);while (true){System.out.println("请输入用户名");String username = scanner.nextLine();System.out.println("请输入密码");String password = scanner.nextLine();StringBuffer sb = new StringBuffer();sb.append("username=").append(username).append("&password=").append(password);sendMessage2Server(socket,"login");sendMessage2Server(socket,sb.toString());BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String str = br.readLine(); // 这里返回登录状态码:1、登录成功 2、密码错误 3、用户名不存在System.out.println(str);switch (str){case "1" -> {System.out.println("登录成功");
//                    new Thread(new Client2Runnable(socket)).start();pool.submit(new Client2Runnable(socket));chat2Server(socket);}case "2" -> System.out.println("密码错误");case "3" -> System.out.println("用户名不存在");}}}private static void chat2Server(Socket socket) throws IOException {Scanner scanner = new Scanner(System.in);while (true){System.out.println("请输入要发送的内容:");String message = scanner.nextLine();sendMessage2Server(socket,message);}}public static void sendMessage2Server(Socket socket,String msg) throws IOException {BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));bw.write(msg);bw.newLine();bw.flush();// 由于使用了缓存输出字符流,所以需要刷新缓冲区}
}class Client2Runnable implements Runnable{Socket socket;public Client2Runnable(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));while (true){String message = br.readLine();System.out.println(message);}} catch (IOException e) {throw new RuntimeException(e);}}
}

服务端:

public class Server {//    服务端
//    定义一个全局变量,存储每个连接到服务端的socket,
//    由于要使用多线程,为了线程安全,这里不建议使用ArrayList
//    static ArrayList<Socket> list = new ArrayList<>();static CopyOnWriteArrayList<Socket> list = new CopyOnWriteArrayList<>();static ThreadPoolExecutor pool;static {pool = new ThreadPoolExecutor(3,6,60,TimeUnit.SECONDS,new ArrayBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());}public static void main(String[] args) throws IOException {ServerSocket ss = new ServerSocket(65535);Properties prop = new Properties();FileInputStream fis = new FileInputStream("F:\\Java\\code\\testcode\\study-javase\\userinfo\\user.txt");prop.load(fis);fis.close();
//        System.out.println(prop);while (true) {Socket socket = ss.accept();// 监听65535端口,等待连接
//            有客户端连接后,拿到这个客户端socketSystem.out.println("有客户端连接成功"); // 每次有一个客户端连接,就开启一条线程去执行接受消息和群发
//            new Thread(new ServerRunnable(socket, prop)).start();pool.submit(new ServerRunnable(socket, prop));}}
}class ServerRunnable implements Runnable {Socket socket;Properties prop;public ServerRunnable(Socket socket, Properties prop) {this.socket = socket;this.prop = prop;}@Overridepublic void run() {try {BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));while (true) {String pd = br.readLine();
//                if (pd == null) {
//                    // 客户端断开连接
//                    System.out.println("客户端断开连接");
//                    break;
//                }System.out.println(pd);if ("login".equals(pd)) {login(br);}}} catch (IOException e) {throw new RuntimeException(e);}}private void login(BufferedReader br) throws IOException {String str = br.readLine();System.out.println(str);String[] strArr = str.split("&");String usernameInput = strArr[0].split("=")[1];String passwordInput = strArr[1].split("=")[1];
//        UserInfo user = UserInfo.builder().username(usernameInput).password(passwordInput).build();if (prop.containsKey(usernameInput)) {if (passwordInput.equals(prop.get(usernameInput))) {
//                登录成功,开始聊天System.out.println("登录成功");sendMessage2Client("1");Server.list.add(socket);
//              开始聊天getAndSendMsg2AllClient(usernameInput);} else {System.out.println("密码错误");sendMessage2Client("2");}} else {System.out.println("用户不存在");sendMessage2Client("3");}}private void getAndSendMsg2AllClient(String usernameInput) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));while (true) {String msg = br.readLine();System.out.println(usernameInput + "说 -> " + msg);Server.list.forEach(s -> {try {sendMessage2Client(s, usernameInput + "说 -> " + msg);} catch (IOException e) {throw new RuntimeException(e);}});}}private void sendMessage2Client(String msg) throws IOException {/*这种写法需要手动拼接 \n 换行符号OutputStream outputStream = socket.getOutputStream();outputStream.write((msg + "\n").getBytes());outputStream.flush();*/BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));bw.write(msg);bw.newLine();bw.flush();}private void sendMessage2Client(Socket s, String msg) throws IOException {
//        OutputStream outputStream = socket.getOutputStream();BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));bw.write(msg);bw.newLine();bw.flush();}
}
/*
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class UserInfo{private String username;private String password;
}
*/

在老师的基础上改了部分内容

效果:

反射

获取Class的三种方式

反射获取构造方法

反射获取成员变量

反射获取成员方法

案例

将传过来的对象里面的值存入本地文件

动态代理

代码实现

http://www.dtcms.com/a/577216.html

相关文章:

  • 便携软件注册器:让便携版的软件秒变默认程序
  • 知识体系(四)Agent
  • 48 进 48 出纯音频矩阵:大型场景音频调度的技术革新与应用实践
  • 男女做暖暖的试看网站漫画网站图片一般多大
  • 萤石开放平台机器人音视频对接流程
  • 站长之家特效网站wordpress 端口号
  • 网页设计与网站建设教材北京企业网站优化
  • 深圳品牌网站设计公司价格深圳非凡网站建设公司
  • 5.基础--SQL--DDL数据库操作
  • 小马智行港股上市:自动驾驶从“技术追跑”到“商业领跑”的里程碑
  • 【stm32协议外设篇】- SU03T 智能语音模块
  • 修改PostgreSQL测试脚本使之在cedardb中运行并分析日志
  • “融资热潮”来临!商用车自动驾驶拐点已至?
  • 告别资源瓶颈与漫长周期:覆盖自动驾驶全研发周期的SiL验证方案
  • SQL50+Hot100系列(11.6)
  • 【Ubuntu】Ubuntu 服务器升级系统操作记录
  • 模具厂咋做网站阿里巴巴网站分类板块做全屏
  • openvela 时钟框架概述
  • 中国室内设计师资格证小企业如何优化网站建设
  • 排序算法稳定性判断
  • 全面详解常见网络协议默认端口号及其应用场景
  • 详解 零拷贝(Zero Copy):mmap、sendfile、DMA gather、splice
  • 学Java第四十二天--------Arrays工具类和Lambda表达式
  • PDF-XChange Editor丨加拿大PDF编辑转换工具
  • 家里的飞牛NAS连接的明明是千兆宽带,异地访问时网速都不对?
  • Eclipse 查找
  • 网站推广计划建设手机网站包括哪些费用
  • 想要导航网站推广怎么做南山区
  • macOS 系统下 Chrome 浏览器安装 HTTPS 证书完整指南
  • HTTP 401 状态码详解:未授权的含义与解决办法