2022-08-02 第三小组 陈迪 学习笔记
多线程:
1、创建线程
在Java中,创建线程有三种方式
1.1、继承Thread类,并且重写run方法
Thread不是抽象类,run也不是抽象方法
class MyThread extends Thread{
@Override
public void run() {
System.out.println("重写的run方法");
}
}
public class Ch01 {
public static void main(String[] args) {
System.out.println(1);
MyThread myThread=new MyThread();
//调用start方法启动一个线程时,会执行重写的run方法的代码
//直接调run就是对象调方法
myThread.start();
// myThread.run();
System.out.println(3);
System.out.println(4);
}
}
线程的优先级(概率问题)
1.2、实现Runnable接口
class MyThread2 implements Runnable{
@Override
public void run() {
System.out.println(2);
}
}
public class Ch02 {
public static void main(String[] args) {
System.out.println(1);
MyThread2 myThread2=new MyThread2();
//如果想要线程启动,必须调用Thread类中的start方法
Thread t=new Thread(myThread2);
t.start();
System.out.println(3);
System.out.println(4);
}
}
1.3、箭头函数(lambda方法)
public class Ch03 {
public static void main(String[] args) {
System.out.println(1);
new Thread(()-> System.out.println(2)).start();
try{
Thread.sleep(10000);
}catch (Exception e){
e.printStackTrace();
}
System.out.println(3);
System.out.println(4);
}
}
1.4、实现Callable接口
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class MyThread3 implements Callable<String>{
public String call() throws Exception{
System.out.println(2);
return "Call方法返回值";
}
}
public class Ch04 {
public static void main(String[] args) {
System.out.println(1);
FutureTask<String>futureTask=new FutureTask<>(new MyThread3());
new Thread(futureTask).start();
System.out.println(3);
System.out.println(4);
}
}
2、守护线程:
java中提供两种类型的线程:
1、用户线程
QQ 主程序就是用户线程。
2、守护程序线程
守护线程为用户线程提供服务,仅在用户线程运行时才需要。
守护线程对后台支持业务很有用
垃圾回收,大多数jvm线程都是守护线程。
创建守护线程:
线程的生命周期
从摇篮到坟墓
NEW: 这个状态是线程未被start()调用执行
RUNNABLE:线程正在JVM中被执行,等待来自操作系统的调度
BLOCKED:阻塞,因为某些原因不能立即执行需要挂起等待
WATTING:无限期等待。需要依赖Object,如果没有唤醒就一直等待。
TIMED_WATTING:有限期等待,线程等待一个指定时间
TERMINATED:终止线程的状态,线程已经执行完毕。
等待和阻塞两个概念有点像,阻塞因为外部原因,需要等待。
等待一般是主动调用方法,发起主动等待,还可以传参确定等待时间
线程安全:
1、cpu多核缓存结构
物理内存:硬盘内存。(固态)
cpu缓存为了提高程序运行的性能,现在CPU在很多方面对程序进行优化
在cpu处理内存数据时,如果内存运行速度太慢,会拖累CPU
CPU分为三级缓存:每个都有L1/L2缓存,L3多核公用。
CPU查数据时:cpu---L1---L2---L3---内存---硬盘
CPU到内存:60---80纳秒
CPU到L3: 15纳秒
CPU到L2: 3纳秒
CPU到L1: 1纳秒
CPU到寄存器:0.3纳秒
cpu每读取一个数据,读取的是与它相邻的64个字节的数据
英特尔提出了一个MESI协议
1、修改态,此缓存被动过,内容与主内存中不同,为此缓存专有
2、专有态,此缓存与主内存一致,但是其他CPU中没有
3、共享态,此缓存与主内存一致,其他缓存也有
4、无效态,此缓存无效,需要在主内存重新读取
【指令重排】:
四条指令,四个人四张纸写下【恭喜发财】。
【可见性】
【线程的争抢】:解决的最好办法是加锁
synchronize同步锁,线程同步
当一个方法加上synchronize修饰,就叫同步方法。
同步:
Java内存模型---JMM
尽量做到硬件和操作系统之间达到一致的访问效果。
volatile:内存屏障
cpu遇到这条指令会停下,去执行未执行完的代码
线程安全的实现方法:
1、数据不可变
一切不可变的对象一定是线程安全的。
对象的方法的实现方法的调用者,不需要再进行任何的线程安全的保障措施
比如final修饰的基本数据类型,字符串
2、互斥同步,加锁。【悲观锁】
3、非阻塞同步。【无锁编程】自旋,用cas来实现
4、无同步方案,多个线程共享数据,又可以在单独的线程中计算,得出结果。把共享数据的可见范围限制在一个线程之内,就无需同步,把共享的数据拿过来。从而保证线程安全。ThreadLocal
心得体会:
今天学习了多线程,大部分都是理论知识,少数是代码,需要深层次的理解和体会,希望可以理解这些内容。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】