总结Thread的基本用法

server/2025/2/13 12:19:47/

1. 线程创建

1.1 创建一个类, 继承Thread, 重写run方法

java">class MyThread extends Thread {@Overridepublic void run() {while (true) {System.out.println("hello thread");try {// 这里只能 try catch, 不能 throws.// 此处是方法重写. Java 的方法重写规则不允许子类抛出比父类方法更多的受检查异常,因为这会破坏方法的调用契约。// Thread 的 run() 方法没有声明抛出任何异常,因此子类重写时也不能抛出受检查的异常。// 在重写的时候, 也就不能 throws 异常了.Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class demo1 {public static void main(String[] args) throws InterruptedException {MyThread myThread = new MyThread();myThread.start();// myThread.run();while (true) {System.out.println("hello main");Thread.sleep(1000);}}
}

1.2 创建一个类, 实现Runnable, 重写run方法

java">class MyRunnable implements Runnable{@Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
public class demo2 {public static void main(String[] args) throws InterruptedException {Runnable runnable = new MyRunnable();Thread t = new Thread(runnable);t.start();while (true) {System.out.println("hello main");Thread.sleep(1000);}}
}

Thread这里是直接把要完成的工作,放到了Thread 的run方法中.
Runnable这里则是分开了,把要完成的工作放到Runnable 中, 再让Runnable和Thread配合.

这种方法就是把线程要执行的任务和线程本身,进一步的解耦合了.

啥是解耦合? 通俗来说就是把之前关系很紧的东西分开了,这样它们之间的相互依赖减少了。
当我们使用并发编程的方式,来完成某个工作时, 就可以用Runnable描述这个工作的具体细节.
使用多线程的方式,就可以使用Runnable搭配线程使用.

使用线程池的方式,就可以使用Runnable搭配线程池使用.

使用协程的方式,也可以使用Runnable搭配协程...

1.3 继承 Thread, 重写run方法, 基于匿名内部类

java">// 通过匿名内部类, 创建线程
public class demo3 {public static void main(String[] args) {Thread t = new Thread() {@Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};t.start();while (true) {System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}



 

1.4 实现 Runnable, 重写run方法, 基于匿名内部类

java">public class Demo4 {public static void main(String[] args) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}
}

1.5 使用lambda表达式,表示run方法的内容

java">public class Demo5 {public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}
}

lambda表达式, 本质上就是一个"匿名函数". 这样的匿名函数, 主要就可以用来作为回调函数来使用.

回调函数, 不需要咱们程序猿自己主动调用而是在合适的时机, 自动的被调用.

上述的"回调函数"就是在线程创建之后, 才能真正地执行.

.经常会用到回调函数的场景:
1.服务器开发:服务器收到一个请求,触发一个对应的回调函数.

2.图形界面开发:用户的某个操作,触发一个对应的回调.

线程的创建并不只是这五种写法

还有基于Callable和基于线程池.

2. Thread 类及常⻅⽅法

这部分推荐大家去看官方文档, https://docs.oracle.com/javase/8/docs/api/

有一些需要注意的点

给线程起个名字

java">public class Demo6 {public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}, "myThread");t.start();}
}

上述代码运行时, 在jconsole中观察没有main线程了, 却有myThread线程.

Thread中的常见属性

后台线程也叫做守护线程, 后台进程不会影响进程结束

前台线程, 前台进程会影响进程结束, 如果前台进程没执行完, 进程是不会结束的

一个进程中所有的前台线程都执行完, 退出了,此时即使存在后台线程仍然没执行完, 也会随着进程一起退出.

我们手动创建的线程默认是前台进程, 可以通过setDaemo显示的设置成后台进程.

java">// 后台线程 和 前台线程
public class Demo7 {public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("hello thread");}});// 设置成后台线程了.t.setDaemon(true);t.start();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}
}

线程是否存活, 这个线程指的是Thread对象对应在系统内核的那个线程.

Thread对象的生命周期, 并不是和系统中的线程完全一致.

一般都是Thread对象,先创建好, 再手动调用start, 内核才真正创建出线程.
消亡的时候, 可能是thread 对象先结束了生命周期(没有引用指向这个对象)

也可能是thread 对象还在, 内核中的线程把 run 执行完了,线程就结束了.
 

启动一个线程 start()

 

 

3. 线程终止

 

那么终止线程应该怎么做呢?

1) 程序猿手动设置标志位

通过这个手动设置的标志位, 来让run尽快结束. 

java">// 线程终止
public class Demo8 {// 写作成员变量就不是触发变量捕获的逻辑了. 而是 "内部类访问外部类的成员" , 本身就是 ok 的~~public static boolean isQuit = false;public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while (!isQuit) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();// 主线程这里执行一些其他逻辑之后, 要让 t 线程结束.Thread.sleep(3000);// 这个代码就是在修改前面设定的标志位.isQuit = true;System.out.println("把 t 线程终止");}
}

 


 



 


 


 


http://www.ppmy.cn/server/167320.html

相关文章

DeepSeek与核货宝订货系统的协同进化:智能商业范式重构

数据处理与分析方面 深度数据洞察:利用Deepseek强大的智能数据挖掘与分析能力,处理核货宝订货系统中的海量订单数据、客户数据、商品数据等。比如分析不同地区、不同时间、不同客户群体的订货偏好和趋势,为批发订货企业制定精准的采购、库存…

CNN-day8-经典神经网络GoogleNet

day9-经典神经网络GoogleNet 1 11卷积 卷积核的尺寸等于1的特例,用来做升维和降维,减少参数量,改变通道数,通道间的特征融合 1.1作用 1.1.1实现通道间特征的融合 常规转换公式:0.2989R 0.5870G 0.1140B import…

我用AI做数据分析之四种堆叠聚合模型的比较

我用AI做数据分析之四种堆叠聚合模型的比较 这里AI数据分析不仅仅是指AI生成代码的能力,我想是测试AI数据分析方面的四个能力,理解人类指令的能力、撰写代码的能力、执行代码的能力和解释结果的能力。如果这四个能力都达到了相当的水准,才可…

Python Web 框架

1. 三个主流的 Python Web 框架: Django:是一个高级的Python Web框架,鼓励快速开发和干净、务实的设计。它具有丰富的功能,如内置的管理界面、数据库抽象层、表单处理等,适用于大型复杂的Web应用开发。FastAPI&#x…

Unity状态机的实现方法一

Unity状态机知识点整理 1. 状态机基本概念 1.1 什么是状态机 Unity常见的状态机管理分为三种: 枚举状态机通过实现接口的方式多态出的更加便于维护的状态机Unity Animator自带的StateMachineBehaviour 1.2 不同状态机实现方式的对比 自定义状态机(…

TDengine 产品由哪些组件构成

目 录 背景产品生态taosdtaosctaosAdaptertaosKeepertaosExplorertaosXtaosX Agent应用程序或第三方工具 背景 了解一个产品,最好从了解产品包括哪些内容开始,我这里整理了一份儿 TDegnine 产品包括有哪些组件,每个组件作用是什么的说明&a…

【算法】动态规划专题⑪ —— 区间DP python

目录 引入进入正题回归经典总结 引入 区间动态规划(区间DP)适用于解决涉及区间最优化的经典问题,如石子合并、最长回文子序列等。 进入正题 石子合并 https://www.acwing.com/problem/content/284/ 有 N 堆石子排成一排,其编号为…

百度舆情优化:百度下拉框中的负面如何清除?

百度的下拉词、相关搜索、大家还在搜有负面词条,一直是企业公关经理头疼的问题,小马识途营销顾问深耕网络营销领域十几年,对百度SEO优化、百度下拉框、百度相关搜索、自媒体营销、短视频营销等等技巧方面积累了一定的方法和技巧。 对于百度下…