Java 基础之线程声明周期与线程的同步
线程的生命周期
JDK中用Thread.State类定义了线程的几种状态
要想实现多线程,必须在主线程中创建新的线程对象。Java语言使用Thread类及其子类的对象来表示线程,在它的一个完整的生命周期中通常要经历如下的五种状态:
新建: 当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件,只是没分配到CPU资源
运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态, run()方法定义了线程的操作和功能
阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出 CPU 并临时中止自己的执行,进入阻塞状态
死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束
同步代码块
线程同步安全问题解决方式一
说明:操作共享数据的代码,即为需要被同步执行的代码
共享数据:多线程共同操作的数据
同步监视器:俗称锁。任何类的对象都可以充当锁
要求:多个线程必须要共用同一把锁
劣势:处理共享数据代码不能并行执行
同步代码方式一继承接口
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 | class win1 implements Runnable{ Object obj = new Object(); private int Tic= 10 ; @Override public void run() { synchronized (obj) { while ( true ) { if (Tic > 0 ) { try { Thread.sleep( 100 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + Tic); Tic--; } else { break ; } } } } } public class wintest { public static void main(String[] args) { win1 w1= new win1(); Thread t1 = new Thread(w1); Thread t3 = new Thread(w1); Thread t2 = new Thread(w1); t1.start(); t2.start(); t3.start(); } } 测试结果 Thread- 0 : 10 Thread- 0 : 9 Thread- 0 : 8 Thread- 0 : 7 Thread- 0 : 6 Thread- 0 : 5 Thread- 0 : 4 Thread- 0 : 3 Thread- 0 : 2 Thread- 0 : 1 Process finished with exit code 0 |
同步代码方式二继承类
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 50 51 52 53 54 | class window2 extends Thread{ private static int tic = 10 ; private static Object obj= new Object(); //多个对象时锁一定要是静态的 @Override public void run() { while ( true ){ synchronized (obj) { if (tic > 0 ) { try { Thread.sleep( 100 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName() + tic); tic--; } else { break ; } } } } } public class ThreadTest1 { public static void main(String[] args) { window2 mthread1= new window2(); // Thread t1= new Thread(mthread); // Thread t2= new Thread(mthread); // Thread t3= new Thread(mthread); // t1.start(); // t2.start(); // t3.start(); window2 mthread2= new window2(); window2 mthread3= new window2(); mthread1.start(); mthread2.start(); mthread3.start(); } } 测试结果 Thread- 010 Thread- 09 Thread- 08 Thread- 07 Thread- 06 Thread- 05 Thread- 04 Thread- 03 Thread- 02 Thread- 01 Process finished with exit code 0 |
同步方法的实现
* 1.同步方法仍然涉及到同步监视器,只是不需要我们声明显示。
* 2.非静态同步方法,同步监视器时:this
* 静态同步方法:同步监视器是当前类本身
同步方法方式一
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 | class window3 implements Runnable{ private static int tic = 10 ; //private static Object obj= new Object();//多个对象时锁一定要是静态的 @Override public void run() { //方法声明为synchronized while ( true ){ show(); } } public synchronized void show(){ //同步监视器时this if (tic > 0 ) { try { Thread.sleep( 100 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "****" + tic); tic--; } } } public class WindowTest3 { public static void main(String[] args) { window3 w1 = new window3(); Thread t1 = new Thread(w1); Thread t3 = new Thread(w1); Thread t2 = new Thread(w1); t1.start(); t2.start(); t3.start(); } } 测试 Thread- 1 **** 10 Thread- 2 **** 9 Thread- 0 **** 8 Thread- 0 **** 7 Thread- 2 **** 6 Thread- 1 **** 5 Thread- 1 **** 4 Thread- 2 **** 3 Thread- 2 **** 2 Thread- 0 **** 1 Process finished with exit code - 1 |
同步方法二
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 50 51 | class window4 extends Thread{ private static int tic = 10 ; //private static Object obj= new Object();//多个对象时锁一定要是静态的 @Override public void run() { while ( true ) { //synchronized (obj) { show(); } //} } public static synchronized void show(){ if (tic > 0 ) { try { Thread.sleep( 100 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "***" + tic); tic--; } } } public class WindoTest4 { public static void main(String[] args) { window4 mthread1 = new window4(); // Thread t1= new Thread(mthread); // Thread t2= new Thread(mthread); // Thread t3= new Thread(mthread); // t1.start(); // t2.start(); // t3.start(); window4 mthread2 = new window4(); window4 mthread3 = new window4(); mthread1.start(); mthread2.start(); mthread3.start(); } } 测试结果 Thread- 0 *** 10 Thread- 0 *** 9 Thread- 2 *** 8 Thread- 2 *** 7 Thread- 1 *** 6 Thread- 2 *** 5 Thread- 0 *** 4 Thread- 0 *** 3 Thread- 2 *** 2 Thread- 2 *** 1 |
单例模式懒汉安全问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class Bank{ private Bank(){ } private static Bank instance= null ; public synchronized static Bank getInstance(){ //方式:效率差 // synchronized (Bank.class) { // // if (instance == null) { // instance = new Bank(); // // } // return instance; // } //方式二 if (instance== null ){ synchronized (Bank. class ) { if (instance== null ) { instance = new Bank(); } } } return instance; } } |
死锁问题
死锁
不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃
自己需要的同步资源,就形成了线程的死锁
出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于
阻塞状态,无法继续
解决方法
专门的算法、原则
尽量减少同步资源的定义
尽量避免嵌套同步
死锁示例
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 | public class ThreadTest { public static void main(String[] args) { StringBuilder s1 = new StringBuilder(); StringBuilder s2 = new StringBuilder(); new Thread(){ @Override public void run() { synchronized (s1){ s1.append( "a" ); s2.append( 2 ); try { Thread.sleep( 100 ); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s2){ s1.append( "b" ); s2.append( "2" ); System.out.println(s1); System.out.println(s2); } } } }.start(); new Thread( new Runnable() { @Override public void run() { synchronized (s2){ s1.append( "c" ); s2.append( 3 ); try { Thread.sleep( 100 ); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s1){ s1.append( "u" ); s2.append( "d" ); System.out.println(s1); System.out.println(s2); } } } }).start(); } } |
草都可以从石头缝隙中长出来更可况你呢
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏