java中的多线程
多线程基础
- 进程:进程就是运行中的程序,当被关闭的时候,这段进程也关闭。比如我们玩玩游戏,打开游戏操作系统会为该进程分配一个空间,当退出游戏是,进程也就结束了
- 线程:线程是由进程创建的,是进程的实体。比如我们下载东西,可以同时下载几个,下载一个就开启一个线程。再比如,qq聊天可以跟多个人聊,一个聊天对话框就是一个线程,可以拥有好几个线程。
- 一个进程可以有多个线程
- 单线程和多线程的基本概念:
- 单线程:同一时刻,只允许执行一个线程
- 多线程:同一时刻,可以执行多给线程,比如qq可以多个聊天窗口
- 并发:同一时刻,多个任务交替执行,造成“貌似同时”的错句,简单的说;单核cpu实现的多任务就是并发。理解:只有一个cpu去执行两个程序,在同一时刻cpu只能去执行一个程序,cpu只能来回切换,执行完一个在执行一个,但是这速度切换的非常快,好似同时执行一样
- 并行:同一时刻,多个任务同时执行。多核cpu可以实现并行,也可能出现并发和并行同时存在。加入我们电脑有两个cpu,有三个程序,这样就有一个是并发一个是并行
线程的基本使用
- 创建线程的两种方式
- 继承Thread类,重写run方法
- 实现Runnable接口,重写run方法
- 说明:当一个类继承了Thread类,该类就可当作线程使用
- 说明:为什么会有两个关于线程的创建方式,因为java是单继承的,因此,继承了Thread就不能继承其他类,所以我们可以使用Runnable接口
- 线程的方法和注意事项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | package com.yc.join; public class join_ { public static void main(String[] args) throws InterruptedException { /** * 1.主线程每隔1s,输出hi,-共10次 * 2.当输出到hi 到5时,启动一个子线程(要求实现Runnable),每隔1s输出hello ,等该线程输出10次hello后,退出 * 3.主线程继续输出hi ,直到主线程退出, */ Thread thread = new Thread( new num()); for ( int i = 0 ;i < 10 ; i++){ System.out.println( "hi" + i ); if (i == 5 ){ //执行线程 thread.start(); //插入线程 thread.join(); } //睡眠1秒 Thread.sleep( 1000 ); } } } class num extends Thread{ private int count = 0 ; @Override public void run() { while ( true ){ System.out.println( "hello" +(++count)); try { //休眠一秒 Thread.sleep( 1000 ); } catch (InterruptedException e) { e.printStackTrace(); } if (count == 10 ){ break ; } } } } |
用户线程和守护线程
用户线程:也叫工作线程,当线程的任务执行完以通知的方式结束
守护线程:一般为工作线程服务,当所有的用户线程结束,守护线程自动结束
常见的守护线程:垃圾回收机制
案例
线程的生命周期
JDK 中用Thread.State 枚举表示了线程的几种状态
线程状态转换图
线程的同步
-
线程同步机制(synchronized)
互斥锁
案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | package com.yc.Homework; /** * (1)有2个用户分别从同一个卡上取钱(总额:10000) * (2)每次都取1000,当余额不足时,就不能取款了 * (3)不能出现超取现象=》线程同步问题. */ public class Homework02 { public static void main(String[] args) { AAA aaa = new AAA(); AAA aaa1 = new AAA(); //aaa1.start();这里不能调用,得用下面的方法 Thread thread = new Thread(aaa); //构造器传入一个对象方便调用 start()方法 thread.start(); Thread thread1 = new Thread(aaa1); thread1.start(); } } class AAA implements Runnable{ private static int Num = 10000 ; private boolean loop = true ; // public synchronized void sun(){ // if (Num<1000){ // System.out.println("余额不足,剩余"+Num); // loop = false; // }else { // System.out.println(Thread.currentThread().getName()+"取出1000,还剩" + (Num-=1000)); // } // } @Override public void run() { while (loop) { // sun(); synchronized ( this ) { if (Num < 1000 ) { System.out.println(Thread.currentThread().getName() + "余额不足,剩余" + Num); loop = false ; } else { System.out.println(Thread.currentThread().getName() + "取出1000,还剩" + (Num -= 1000 )); try { Thread.sleep( 1000 ); } catch (InterruptedException e) { e.printStackTrace(); } } } } } } |
-
注意事项和细节
线程的死锁
-
案例
释放锁
下面操作会释放锁
下面操作不会释放锁
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧