实训笔记6.25

news2024/12/26 12:36:59

实训笔记6.25

  • 6.25
    • 一、座右铭
    • 二、知识回顾
      • 2.1 JavaSE
        • 2.1.1 基本语法
        • 2.1.2 数组
        • 2.1.3 JVM内存
        • 2.1.4 面向对象
        • 2.1.5 Java常用类
        • 2.1.6 Java异常机制
        • 2.1.7 Java泛型
        • 2.1.8 Java集合
        • 2.1.9 JavaIO流
        • 2.1.10 Java注解
        • 2.1.11 Java反射机制
        • 2.1.12 Java多线程
        • 2.1.13 Java网络编程
    • 三、Java多线程
      • 3.1 多线程的基本概念
        • 3.1.1 程序、进程和线程
        • 3.1.2 单核CPU和多核CPU问题
        • 3.1.3 并行和并发
      • 3.2 Java多线程的问题
      • 3.3 Java当中如何创建和启动多线程类
      • 3.4 Thread类常用方法
      • 3.5 线程的生命周期
      • 3.6 线程的数据同步问题--共享数据问题
        • 3.6.1 JVM堆区和元数据的数据对于多线程是共享的,堆区如果共享必须满足数据在堆区是唯一的
        • 3.6.2 继承Thread类实现的线程和Runnable、Callable实现的线程有什么区别
        • 3.6.3 如何解决共享数据的安全性问题
      • 3.7 线程的通信问题--线程之间如何交流

6.25

一、座右铭

我的故事你说,我的文字我落,我值几两你定,我去何方我挑。

二、知识回顾

2.1 JavaSE

2.1.1 基本语法

  1. 标识符、关键字、保留字
  2. 数据类型
  3. 变量、常量、字面量
  4. 运算符
  5. 控制流程

2.1.2 数组

2.1.3 JVM内存

2.1.4 面向对象

  1. 类和对象
  2. 三大特征
  3. 抽象类、抽象方法、接口
  4. 常见关键字:package、import、this、super、static、final、instanceof、enum

2.1.5 Java常用类

  1. 枚举类
  2. JavaBean类、lombok
  3. Object类
  4. 包装类
  5. String、StringBuffer、StringBuilder
  6. System类
  7. Arrays类
  8. 时间日期类
    1. Date
    2. SimpleDateFormat
    3. Calendar
  9. Math、Scanner、Random
  10. Java比较器

2.1.6 Java异常机制

2.1.7 Java泛型

2.1.8 Java集合

  1. Collection
    1. List
    2. Set
  2. Map

2.1.9 JavaIO流

  1. 四大基类

  2. 常用IO流

    1. 节点流
      1. 数组流
      2. 文件流
    2. 功能流
      1. 缓冲流
      2. 转换流
      3. 对象流
      4. 打印流
      5. 标准输入和输出流
  3. IO流使用完毕要注意关闭、IO流要配套使用

2.1.10 Java注解

注解的四大元注解

2.1.11 Java反射机制

  1. Class类
  2. 通过Class类去获取类中的组成成分
  3. 通过获取的类中成分去调用相对应的内容

2.1.12 Java多线程

2.1.13 Java网络编程

三、Java多线程

3.1 多线程的基本概念

3.1.1 程序、进程和线程

程序:没有运行起来的代码块

进程:运行起来的程序叫做进程

线程:线程是进程的组成单位,是资源分配的最小单位

3.1.2 单核CPU和多核CPU问题

CPU内核是用来运行线程的最小单位,CPU的一个内核在某一时刻只能运行一个线程。

但是我们电脑上线程的数量是远大于内核数的,也就意味着一个CPU内核同时运行几百个线程。 CPU的调度机制:时间片调度机制

3.1.3 并行和并发

并行:同一时刻多个线程同时运行

并发:同一时刻只能运行一个线程,多个线程抢占时间片运行,给人的感觉就好像是同时运行

3.2 Java多线程的问题

Java的JVM内存本身就是支持多线程运行的,也就意味着Java可以开发多线程程序的。JVM内存分为五部分,Java当中每启动一个线程,会给这个线程启动一个独立的虚拟机栈区和程序计数器,而堆区和元数据区对于多个线程是共享的。

3.3 Java当中如何创建和启动多线程类

1、借助Java中Thread类–Thread类是java.lang包的,是Java中所有多线程类的顶尖父类

2、借助Java中Runnable接口创建多线程

3、借助Java中的Callable接口创建多线程

4、借助Java中的线程池创建多线程

启动多线程只有一种方式:借助Thead线程类中的start方法来启动

启动多线程只有一种方式:
借助Thead线程类中的start方法来启动

代码示例:

/**
 * 线程的第一种创建和使用方式:
 *   1、继承Thread线程类,并且重写run方法---run方法中就是线程启动起来以后需要执行的业务逻辑
 *   2、创建一个这个类的实例对象,然后调用start方法启动多线程
 *   
 * 想要通过Java一个线程输出0-100以内的所有偶数,另外一个线程输出0-100以内的所有奇数
 * 
 * 一个Java程序,没有创建多线程的情况下,有几个线程?
 *     1、main线程
 *     2、垃圾回收线程
 *     3、异常处理线程
 *   如果我们要开启多线程,需要在main线程执行过程中开启另外一个线程
 * @author 11018
 *
 */
public class Demo01 {
	public static void main(String[] args) {
//		T t = new T();
//		t.start();
		Thread t = new Thread() {
			@Override
			public void run() {
				for (int i = 0; i <= 100; i++) {
					if(i % 2 == 0) {
						System.out.println("有一个偶数为:"+i);
					}
				}
			}
		};
		t.start();
		
		for (int i = 0; i <= 100; i++) {
			if(i % 2 == 1) {
				System.out.println("有一个奇数为:"+i);
			}
		}
	}

}
class T extends Thread{
	@Override
	public void run() {
		for (int i = 0; i <= 100; i++) {
			if(i % 2 == 0) {
				System.out.println("有一个偶数为:"+i);
			}
		}
	}
}
/**
 * 创建多线程的第二种方式:实现Runnable接口
 *   1、实现Runnable接口,然后重写run方法
 *   2、创建一个实现类的对象,然后创建一个Thread类对象,把实现类对象当中参数传入到Thread类的构建中
 *   3、启动thead类的start方法
 * @author 11018
 */
public class Demo02 {
	public static void main(String[] args) {
		A a = new A();
		Thread t = new Thread(a);
		t.start();
		
		for (int i = 0; i <= 100; i++) {
			if(i % 2 == 1) {
				System.out.println("有一个奇数为:"+i);
			}
		}
	}
}
class A implements Runnable{
	@Override
	public void run() {
		for (int i = 0; i <= 100; i++) {
			if(i % 2 == 0) {
				System.out.println("有一个偶数为:"+i);
			}
		}
	}
}
/**
 * 线程的第三种创建方式:Callable接口
 *   1、实现类实现callable接口,然后重写call()方法
 *   2、创建一个实现类的对象,然后创建FutureTask类包含实现类对象
 *   3、创建一个Thread类包含Fuxxxxx 然后调用thread类的start方法开启多线程
 * @author 11018
 *
 */
public class Demo03 {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		B b = new B();
		FutureTask<Integer> ft = new FutureTask<>(b);
		Thread t = new Thread(ft);
		t.start();
		
		for (int i = 0; i <= 100; i++) {
			if(i % 2 == 1) {
				System.out.println("有一个奇数为:"+i);
			}
		}
		System.out.println(ft.get());
	}

}
class B implements Callable<Integer>{
	@Override
	public Integer call() throws Exception {
		for (int i = 0; i <= 100; i++) {
			if(i % 2 == 0) {
				System.out.println("有一个偶数为:"+i);
			}
		}
		return 0;
	}
}

		Runnable r = new Runnable() {
			@Override
			public void run() {
				int sum = 0;
				for (int i = 1; i <= 5; i++) {
					sum += i;
				}
				System.out.println(sum);
			}
		};
		Thread t= new Thread(r);
		t.start();
		
		int sum = 1;
		for (int i = 1; i <= 5; i++) {
			sum *= i;
		}
		System.out.println(sum);

3.4 Thread类常用方法

Thread类是线程启动运行的核心类,内部提供了很多和线程有关的方法

方法名作用
run()方法Thread类继承的Runnable接口,多线程启动成功以后自动执行的代码方法
start()方法开启一个线程,线程一旦开启以后,会自动调用run方法执行其中的业务逻辑
stop()方法强制停止一个线程
setName(String name)给当前线程设置一个别名,如果没有设置,会有一个默认线程名
getName()获取设置的别名----设置的别名不一定是一个独立的线程
static currentThread():Thread获取当前程序运行所属的线程
static sleep(long timestrap)让当前线程睡上一定的毫秒数
setPriorit(int num)设置线程的优先级,优先级高的更容易获取CPU的执行权 1-10 优先级设置必须在线程开启之前设置
yield():void让当前线程丧失CPU的执行权,让优先级高的去获取CPU的执行权
join():void线程加入,将另外一个线程加入到当前线程中,只有当加入的线程执行完成,当前线程才能继续向后执行
setDaemon(boolean flag)设置 true线程为守护线程
isDaemon():boolean测试线程是否为守护线程

3.5 线程的生命周期

五个阶段:创建、就绪、执行、阻塞、死亡

在这里插入图片描述

3.6 线程的数据同步问题–共享数据问题

3.6.1 JVM堆区和元数据的数据对于多线程是共享的,堆区如果共享必须满足数据在堆区是唯一的

3.6.2 继承Thread类实现的线程和Runnable、Callable实现的线程有什么区别

  1. 继承Thread类线程共享数据很难操作
  2. 实现方式做的线程本身就是线程共享的

3.6.3 如何解决共享数据的安全性问题

同步代码块

synchronized(同步监视器--锁的钥匙){ 操作共享数据的代码块; }

同步方法

案例:

/**
 * 做一个买火车票的程序,三个窗口同时卖100张票
 * @author 11018
 *
 */
public class Demo01 {
	public static void main(String[] args) {
//		TrainTicket tt = new TrainTicket();
		Window one = new Window();
		one.setName("window1");
		Window two = new Window();
		two.setName("window2");
		Window three = new Window();
		three.setName("window3");
		one.start();
		two.start();
		three.start();
	}
}
  1. 将操作共享数据的代码块抽取到一个独立的方法中,然后再方法上加上synchronized关键字

    代码示例:

    public class Demo02 {
    	public static void main(String[] args) {
    		NewWindow nw = new NewWindow();
    		Thread one = new Thread(nw);
    		Thread two = new Thread(nw);
    		Thread three = new Thread(nw);
    		one.start();
    		two.start();
    		three.start();
    	}
    
    }
    class NewWindow implements Runnable{
    	int num = 100;
    	@Override
    	public void run() {
    		while(true) {
    			int saleTicket = saleTicket();
    			if (saleTicket == 0) {
    				break;
    			}
    		}	
    	}
    	
    	public synchronized int saleTicket() {
    		if(num > 0) {
    			System.out.println(Thread.currentThread().getName()+"窗口卖出了第"+num+"张票,还剩余"+(--num)+"张票");
    			return 1;
    		}else {
    			return 0;
    		}
    	}
    }
    
    
  2. 静态方法 该类的.class实列

  3. 普通方法 this

  4. 同步方法再实现接口的线程类中可以实现安全性问题解决,继承体系下实现解决安全性问题比较复杂的。

上锁lock显示的上锁、释放锁:把操作共享数据的代码块放到一个try catch代码块当中,然后再try块显示的上锁 在finally块显示的释放锁

代码示例:

public class Demo03 {
	public static void main(String[] args) {
		WD w = new WD();
		FutureTask<String> ft = new FutureTask<>(w);
		FutureTask<String> ft1 = new FutureTask<>(w);
		FutureTask<String> ft2 = new FutureTask<>(w);
		Thread t = new Thread(ft);
		Thread t1 = new Thread(ft1);
		Thread t2 = new Thread(ft2);
		t.start();
		t1.start();
		t2.start();
		
	}
}
class WD implements Callable<String>{
	ReentrantLock lock = new ReentrantLock();
	int num = 100;
	@Override
	public String call() throws Exception {
		while (true) {
			try {
				lock.lock();
				if(num > 0 ) {
					System.out.println(Thread.currentThread().getName()+"窗口卖出了第"+num+"张票,还剩余"+(--num)+"张票");
				}else {
					break;
				}
			} catch (Exception e) {
				// TODO: handle exception
			}finally {
				lock.unlock();
			}
			
		}
		return null;
	}
}

**死锁:**我要的钥匙被别人用了,别人用的要是我用了

代码示例:

Thread t = new Thread() {
			@Override
			public void run() {
				synchronized (String.class) {
					System.out.println("线程正在执行中");
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					synchronized (StringBuffer.class) {
						System.out.println("线程的第二个逻辑正在执行");
					}
				}
			}
		};
		Thread t1 = new Thread() {
			@Override
			public void run() {
				synchronized (StringBuffer.class) {
					System.out.println("线程正在执行中");
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					synchronized (String.class) {
						System.out.println("线程的第二个逻辑正在执行");
					}
				}
			}
		};
		t.start();
		t1.start();

3.7 线程的通信问题–线程之间如何交流

多个线程之间互相“交流”,多个线程去通过交流去决定谁获得CPU执行,谁阻塞暂停执行

通信是通过Object类的三个方法来完成的:

方法名作用
wait让当前线程失去CPU执行权,进入阻塞状态
notify唤醒整个进程中通过wait方法进入阻塞状态的线程—优先级最高的被唤醒的概率高一点
notifyAll唤醒整个进程中所有通过wait方法进入阻塞状态的线程

线程通信的方法只能使用在同步代码块或者同步方法中,而且线程通信的三个方法调用者是同步监视器。

线程通信在同步代码和同步方法中,先使用notify/notifyall唤醒wait的线程,然后在代码块的最后再wait让当前线程进入阻塞状态

多线程通信时,多线程使用的同步监视器必须是同一个

代码示例:

package com.sxuek.thread.communication;
/**
 * 让两个线程交替打印0-100
 * @author 11018
 *
 */
public class Demo {
	public static void main(String[] args) {
		D d = new D();
		Thread t1 = new Thread(d);
		t1.setPriority(1);
		Thread t2 = new Thread(d);
		t2.setPriority(5);
		Thread t3 = new Thread(d);
		t3.setPriority(10);
		t1.start();
		t2.start();
		t3.start();
	}

}
class D implements Runnable{
	int num = 0;
	@Override
	public void run() {
		while(true) {
			synchronized (String.class) {
				String.class.notify();
				if(num > 100) {
					break;
				}else {
					System.out.printf("%s线程打印了数字%d\n", Thread.currentThread().getName(),num);
					num++;
				}
				try {
					String.class.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}
		
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/683958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用SpringBoot和javafx进行桌面开发

原文合集地址如下&#xff0c;有需要的朋友可以关注 本文地址 合集地址 众所周知&#xff0c;SpringBoot是一款强大的Javaweb开发程序&#xff0c;这得益于其构造了一个Spring容器&#xff0c;然后通过依赖注入和控制反转&#xff0c;维护起一套Java对象和实例的管理机制&…

Chatgpt三大新功能曝光:记住你是谁/文件上传/切换工作区

今日&#xff0c;一张神秘的截图&#xff0c;曝光了chatgpt还没发布的三个新功能&#xff1a; 除截图外&#xff0c;其对应的源代码也被扒了出来&#xff0c;甚至还有人为此建立了GitHub仓库&#xff0c;以此来追踪代码的变化情况。 根据观察&#xff0c;相关部分代码正在更新…

制作看大片一样的推拉镜头效果,刚一个月AI绘图神器 Midjourney 又又更新了

5.1 版本刚更新一个月&#xff0c;官方又宣布 5.2 版本更新了&#xff1a;改进的美观性、连贯性、更好的文本理解、更清晰的图像、更高的变化模式、缩小绘画&#xff0c;以及用于分析提示符号的新命令 /short 命令‍‍‍‍‍‍‍‍‍ 视觉效果最神奇的功能要数 “Zoom Out” 缩…

使用Rabbitmq死信队列解锁库存

一、库存解锁的场景 RabbitMQ库存解锁的场景有很多&#xff0c;以下是一些常见的场景&#xff1a; 订单取消和订单回滚。下订单成功&#xff0c;订单过期没有支付被系统自动取消、被用户手动取消。都要解锁库存。 下订单成功&#xff0c;库存锁定成功&#xff0c;接下来的业务…

《面试1v1》Redis持久化

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

css基础知识七:元素水平垂直居中的方法有哪些?如果元素不定宽高呢?

一、背景 在开发中经常遇到这个问题&#xff0c;即让某个元素的内容在水平和垂直方向上都居中&#xff0c;内容不仅限于文字&#xff0c;可能是图片或其他元素 居中是一个非常基础但又是非常重要的应用场景&#xff0c;实现居中的方法存在很多&#xff0c;可以将这些方法分成…

3.用python写网络爬虫,下载缓存

目录 3.1 为链接爬虫添加缓存支持 3.2 磁盘缓存 3.2.1 实现 3.2.2缓存测试 3.2.3节省磁盘空间 3.2.4 清理过期数据 3.2.5缺点 3.3 数据库缓存 3.3.1 NoSQL 是什么 3.3.2 安装 MangoDB 3.3.3 MongoDB 概述 3.3.4 MongoDB 缓存实现 3.3.5 压缩 3.3.6 缓存测试 3.4 本章…

变分自编码(VAE,Variational Auto-Encoder)知识点速览

目录 1. 主要思想 2. 训练和推理过程 3. 编码器和解码器的结构 4. 主要用途 5. 相较于 auto-encoder 的优劣 1. 主要思想 变分自编码器&#xff08;Variational AutoEncoder&#xff0c;简称VAE&#xff09;是一种生成模型&#xff0c;它通过对数据的隐含表示&#xff08;l…

红日靶场(一)外网到内网速通

红日靶场&#xff08;一&#xff09; 下载地址&#xff1a;http://vulnstack.qiyuanxuetang.net/vuln/detail/2/ win7:双网卡机器 win2003:域内机器 win2008域控 web阶段 访问目标机器 先进行一波信息收集&#xff0c;扫一下端口和目录 扫到phpmyadmin&#xff0c;还有一堆…

韶音和cleer、南卡对比哪个好?韶音、南卡、Cleer开放式耳机横评

现如今&#xff0c;不管是通勤路上还是在家休闲娱乐&#xff0c;又或者是运动时&#xff0c;经常能看见很多人佩戴着耳机听音乐&#xff0c;但是&#xff0c;经常佩戴耳机听音乐的小伙伴都知道&#xff0c;入耳式耳机佩戴久了&#xff0c;容易造成耳部酸痛感、胀痛感&#xff0…

Android 安卓开发语言kotlin与Java该如何选择

一、介绍 如今在Android开发中&#xff0c;应用层开发语言主要是Java和Kotlin&#xff0c;Kotlin是后来加入的&#xff0c;主导的语言还是Java。kotlin的加入仿佛让会kotlin语言的开发者更屌一些&#xff0c;其实不然。 有人说kotlin的引入是解决开发者复杂的逻辑&#xff0c;并…

【VSCode】设置关键字高亮的插件 | Highlight Word

目录 一、概述二、安装 highlight-words 插件三、配置 highlight-words 插件3.1 默认配置3.2 修改 settings.json 配置文件 四、设置高亮快捷键F8五、效果演示 一、概述 本文主要介绍在 VSCode 看代码时&#xff0c;怎样使某个单词高亮显示&#xff0c;主要通过以下三步实现&am…

Docker的run流程

底层原理 Docker怎么工作&#xff1f; Docker为什么比VM虚拟机块&#xff1f; 1.Docker有比虚拟机更少的抽象层 2.docker利用的是宿主机的内核&#xff0c;vm需要是Guest OS 所以说&#xff0c;新建一个容器的时候&#xff0c;docker不需要像虚拟机一样加载一个系统内核&am…

[conda]tf_agents和tensorflow-gpu安装傻瓜式教程

1.打开终端或Anaconda Prompt&#xff08;Windows用户&#xff09;。 2.输入以下命令创建新的Python环境&#xff1a; conda create --name <env_name> python<version>其中&#xff0c;<env_name>是您想要创建的环境名称&#xff0c;<version>是您想…

保留纵向连续性的迭代次数估算方法

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入有3个节点&#xff0c;训练集AB各由5张二值化的图片组成&#xff0c;让B全是0&#xff0c;让差值结构中有6个1.其中有3组 差值结构 A-B 迭代次数 行分布 列分布 0 1 1 0 1 1 3*5*1*2*0-0*0*0*0*0 3977.834 0 1 …

springboot中自定义JavaBean返回的json对象属性名称大写变小写问题

文章目录 springboot中自定义JavaBean返回的json对象属性名称大写变小写问题一、继承类二、手动添加Get方法三、JsonProperty四、spring-boot json(jackson)属性命名策略 springboot中自定义JavaBean返回的json对象属性名称大写变小写问题 开发过程中发现查询返回的数据出现自…

模拟电路系列分享-运放的关键参数3

目录 概要 整体架构流程 技术名词解释 1.输入电压范围 2.优劣范围: 3.理解 技术细节 1.共模抑制比 2.优劣范围 3.理解 小结 概要 提示&#xff1a;这里可以添加技术概要 实际运放与理想运放具有很多差别。理想运放就像一个十全十美的人&#xff0c;他学习100 分&#xff0c;寿…

chatgpt赋能python:Python中的相加功能函数:介绍、应用和示例

Python中的相加功能函数&#xff1a;介绍、应用和示例 Python是一个功能强大的编程语言&#xff0c;拥有许多强大的内置函数和模块。其中一个非常常见的功能是相加或者加法操作。让我们看一下Python中的相加功能函数。 什么是相加&#xff1f; 简而言之&#xff0c;相加是将…

6.17、进程与线程

比如&#xff0c;一边游戏&#xff0c;一边qq聊天&#xff0c;一边听歌&#xff0c;怎么设计&#xff1f; 进程 进程&#xff08;process&#xff09;&#xff1a;程序的一次执行过程&#xff0c;或是正在内存中运行的应用程序。如&#xff1a;运行中的QQ&#xff0c;运行中…

二叉树的基本操作(如何计算二叉树的结点个数,二叉树的高度)

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;&#x1f35f;&#x1f32f;C语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f…