首页IT科技多线程高并发问题(【多线程与高并发】- 线程基础与状态)

多线程高并发问题(【多线程与高并发】- 线程基础与状态)

时间2025-09-19 00:03:54分类IT科技浏览5511
导读:线程基础与状态 ?生命不息,写作不止...

线程基础与状态

?生命不息                 ,写作不止

? 继续踏上学习之路                        ,学之分享笔记

? 总有一天我也能像各位大佬一样

? 一个有梦有戏的人 @怒放吧德德

?分享学习心得        ,欢迎指正                 ,大家一起学习成长!

前言

好久没坚持学习了                        ,所以        ,这次要好好下定决心学习                 。多线程与高并发不是一天两天就能弄懂的         ,需要不断的学习                 、实践                        ,本次笔者将最近学习的内容知识记录下来                        。多线程也是一项比较重要的内容                ,虽然CRUD不太会接触到         ,但是                         ,在一些相关场景可能会有某些问题是由于线程导致的        。

线程的概念

要了解线程的概念                ,就需要知道什么是进程                 。简单理解就是一个进程中包含了许多个线程                        。现在就简单介绍,后续若是有对操作系统进行研究的话会慢慢介绍                         ,具体关于线程进程的内容可以去看看王道的操作系统                        ,里面讲述得特别清楚        。

什么是进程?

是系统进行资源分配的基本单位,是操作系统结构的基础                 ,进程是线程的容器         。程序是指令                        、数据及其组织形式的描述                        ,进程是程序的实体                        。

什么是线程?

所谓线程就是操作系统(OS)能够进行运算调度的最小单位        ,是一个基本的CPU执行单元                 ,也是执行程序流的最小单元                。能够提高OS的并发性能                        ,减小程序在并发执行时所付出的时空开销         。线程是进程的一个实体        ,是被系统独立调度和分派的基本单位                         。线程本身是不拥有系统资源的         ,但是它能够使用同属进程的其他线程共享进程所拥有的全部资源                。

在Java线程中是怎样的呢?

在Java中                        ,最常见得就是继承Thread类或者实现Runnable接口                ,再通过run或者start方法去执行线程。

如以下代码         ,这是一段很简单得代码块                         ,通过继承Thread类                ,重写run方法来创建线程,并且通过run和start来运行                         。 public class Thread_demo01 { private static class Thread1 extends Thread { @Override public void run() { for (int i = 0; i < 5; i++) { try { Thread.sleep(1); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("Thread1-" + i); } } } public static void main(String[] args) { new Thread1().run(); // 顺序执行 // new Thread1().start(); // 线程同时执行 for (int i = 0; i < 5; i++) { try { Thread.sleep(1); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("main"); } } }

这两种不同得启动方式                         ,出现得现象也是不同的                        。

使用run方法启动线程

使用start方法启动线程

关于这两种方式启动线程可以看一下下面的流程图。

run方法是会让线程T1先执行完毕之后                        ,再继续执行主线程,而start方法他是同时执行两个线程                 。

Java线程的Sleep        、Yield                 、Join方法

1                        、sleep方法

sleep()需要提供一个时间参数(毫秒)                 ,会使得线程在一定的时间内被暂停执行                        ,在sleep的过程中        ,线程是不会释放锁的                 ,只会进入阻塞状态                        ,让出cpu给其他线程去执行                        。如下代码演示        ,此处不做锁的探究        。

public class T3_Thread_Sleep { public static void main(String[] args) { Thread t1 = new Thread(new Thread1()); Thread t2 = new Thread(new Thread2()); t1.start(); t2.start(); } static class Thread1 implements Runnable { @Override public void run() { System.out.println("T1 is running"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("T1 is end"); } } static class Thread2 implements Runnable { @Override public void run() { System.out.println("T2 is running"); try { Thread.sleep(2000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("T2 is end"); } } }

运行之后在T1线程休眠的时候会让出cpu资源给T2线程         ,T1线程会睡眠1秒                        ,T2睡眠2秒                ,最终结果如图

2        、Yield方法

yield()与sleep()都是让线程暂停执行         ,也是不会释放锁资源                 。但是yield并不是让进程进入阻塞态                         ,而是回到就绪态                ,等待重新获取CPU资源                        。此时,其他的线程有机会获得cpu资源                         ,也有可能在yield方法进入就绪态后立马变成执行态        。如以下代码                        ,同样不考虑锁的问题         。

public class T4_Thread_Yield { static class Thread1 implements Runnable { @Override public void run() { System.out.println("T1 is running"); Thread.yield(); System.out.println("T1 is end"); } } static class Thread2 implements Runnable { @Override public void run() { System.out.println("T2 is running"); System.out.println("T2 is end"); } } public static void main(String[] args) { Thread t1 = new Thread(new Thread1()); Thread t2 = new Thread(new Thread2()); t1.start(); t2.start(); } }

经过不同的测试,结果都是不同的                        。

3         、Join方法

join()方法是暂停当前线程                 ,调用执行另一个线程                        ,等待join的线程执行完毕后才能够继续执行当前线程                。如以下例子        ,T1,T2同时开始                 ,在T2线程中join了T1                        ,就会导致T1要先执行完毕之后        ,才会去执行T2         。

public class T5_Thread_Join { public static void main(String[] args) { Thread T1 = new Thread(() -> { System.out.println("T1开始"); for (int i = 0; i < 5; i++) { System.out.println("线程T1执行中: " + i); } System.out.println("T1结束"); }); Thread T2 = new Thread(() -> { System.out.println("T2开始"); for (int i = 0; i < 5; i++) { System.out.println("线程T2执行中: " + i); if (i == 3) { try { T1.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } } } System.out.println("T2结束"); }); T1.start(); T2.start(); } }

结果如下         ,不管怎么测试                        ,都会是T2最后执行结束                         。

Java的线程状态

线程具有最基本的三态(就绪                        、运行                、阻塞)                。线程与进程一样                ,各线程之间也存着共享资源和互相合作的制约关系         ,致使线程运行时具有间断性。接下来看一下如图                         ,这是五种状态的转化                         。

线程的不同状态

在Java线程中有6中状态                ,从线程的创建到线程的终止                        。线程创建为NEW创建态,通过start启动线程                         ,线程内部会从就绪态转成运行态                        ,在Java线程中统称为“运行态                 ”,线程由于被挂起         、调用yeild等方法能够使线程从运行态转成就绪态                 ,也能够通过线程的其他方法或者锁阻塞线程                        ,直到时间结束或者是获得锁等        ,从而回到RUNABLE状态。

初始(NEW):新创建了一个线程对象                 ,但还没有调用start()方法                 。 运行(RUNNABLE):Java线程中将就绪(Ready)和运行中(Running)两种状态笼统的称为“运行                        ”                        。线程对象创建后                        ,其他线程(比如main线程)调用了该对象的start()方法        。该状态的线程位于可运行线程池中        ,等待被线程调度选中         ,获取CPU的使用权                        ,此时处于就绪状态(Ready)                 。就绪状态的线程在获得CPU时间片后变为运行中状态(Running)                        。 阻塞(BLOCKED):表示线程阻塞于锁        。 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)         。 超时等待(TIMED_WAITING):该状态不同于WAITING                ,它可以在指定的时间后自行返回                        。 终止(TERMINATED):表示该线程已经执行完毕                。

Java线程的状态转化

如线程状态转换图         ,以下就是Java线程状态的转换流程         。线程可以通过实现Runnable接口或者继承Threa类                         ,然后去实例化Java的线程对象                         。在线程被执行之前都是属于创建态(NEW)                ,在调用start方法后,线程就会转成RUNABLE状态                         ,在RUNABLE中                        ,当线程处于就绪态(Ready)的时候,经过调度分配了cpu资源                 ,这时转成了运行态                        ,当线程被挂起                         、线程执行了yield        ,线程将会退回就绪态                。在运行态(RUNABLE)                 ,也会通过一些处理而被阻塞或者等待。终止状态(TERMINATED)是线程执行完毕退出                        ,此时        ,终止态的线程不会直接转成创建态                         。

Java线程状态代码

Java中线程的状态都是在java.lang.Thread.State

的枚举类中                        。

可以看一下以下枚举代码         ,分别为(NEW                、RUNNABLE、BLOCKED                         、WAITING                        、TIMED_WAITING、TERMINATED)六种。 public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED; }

接下来看一下演示代码

public class T6_Thread_State { static class Thread1 extends Thread { @Override public void run() { System.out.println("run - 当前线程的状态: " + this.getState()); for (int i = 0; i < 5; i++) { try { System.out.println("sleep前 - 当前线程的状态: " + this.getState()); Thread.sleep(1000); System.out.println("sleep后 - 当前线程的状态: " + this.getState()); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public static void main(String[] args) throws InterruptedException { Thread1 t1 = new Thread1(); System.out.println("main - 当前线程的状态: " + t1.getState()); t1.start(); System.out.println("join前 - 当前线程的状态: " + t1.getState()); t1.join(); System.out.println("join后 - 当前线程的状态: " + t1.getState()); } }

运行结果                        ,可以只管看到线程在运行过程种的状态切换                 。

博文推荐

这里推荐给各位一篇很不错的博客文章                ,是针对Java线程的状态转换的详细介绍

Java线程的6种状态及切换(透彻讲解)_潘建南的博客-CSDN博客_线程的5种状态

线程池 waiting on condition_Java线程生命周期与状态切换_有所不知的博客-CSDN博客

?创作不易         ,如有错误请指正                         ,感谢观看!记得点赞哦!?

声明:本站所有文章                ,如无特殊说明或标注,均为本站原创发布                        。任何个人或组织                         ,在未征得本站同意时                        ,禁止复制                 、盗用                        、采集        、发布本站内容到任何网站                 、书籍等各类媒体平台        。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理                 。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
短视频网站设计(极致SEO技巧:打造短视频网页入口,网站推广新风尚) 程序员以后的出路(程序员未来是不是会大量失业?)