并发编程(三)Thread类详解
文章更新时间:2021/09/06
一、引言
Thread类中存在着许多操作线程的方法,学习Thread类是非常有必要的,前面我们也嘘唏了创建线程的几种方式,若线程的创建不是以继承Thread类的方式创建的,那我们又改如何使用Thread中的方法呢?下面一起来学习一下多线程操作的重点--Thread类。
二、实例详解
/** * 认识Thread类的常用方法 */ public class MyThread { public static void main(final String[] arguments) throws InterruptedException { /*一个以实现Runnable接口的方式创建的线程,如何使用Thread类中的方法?*/ //1、创建一个线程实例(此线程是以实现Runnable接口的方式创建的) TestThread runableThread = new TestThread(); //2、通过Thread类的构造函数,用刚才创建的线程生成一个Thread类的实例 Thread thread = new Thread(runableThread); /*Thread类中重要的操作线程方法*/ thread.setName("线程1");//设置线程名称 thread.setPriority(1);//设置线程优先级(1~10;默认为5;10为最高优先级;优先级高并不一定就先执行!) thread.setDaemon(false);//设置该线程是否为守护线程(true:是;false:不是) thread.start();//启动线程 thread.isAlive();//查看当前线程是否存活 thread.join(3000L);//等待该线程执行X秒后再执行下面的代码(PS:若设值大于线程执行时间,则执行完毕后立即执行下面的线程) thread.interrupt();//终止线程(PS:若线程中存在sleep方法,且线程还没运行完毕,调用interrupt时会报错) /*Thread类中的静态方法*/ thread.sleep(1000L);//线程休眠1秒(当前线程回到可执行状态,并不一定能立即执行!) thread.yield();//暂停执行当前线程,并执行其他线程(当前线程回到可执行状态)PS:也有可能刚暂停一下,当前线程立马就获得CPU时间片又继续执行 thread.currentThread();//返回当前线程的实例对象 } }
三、ThreadLocal
什么是ThreadLocal
定义:每一个Thread对象均含有一个ThreadLocalMap类型的成员变量threadLocals,它存储本线程中所有ThreadLocal对象及其对应的值。
作用:维护一个归属线程所有的变量,再整个线程存活期间都可以获取出来。
好处:
- 1、若一条业务线内部需要使用一个变量执行很多方法,那么使用ThreadLocal就可以不用每个方法都显式声明该变量。
- 2、由于ThreadLocal是线程安全的,那么线程中特有的公共变量可以用这种形式来封装
小结:
- ThreadLocalMap 由一个个 Entry 对象构成。
- Entry 继承自 WeakReference<ThreadLocal<?>> ,一个 Entry 由 ThreadLocal 对象和 Object 构成。
- 执行threadLocal.set()方法时,ThreadLocal首先会获取当前线程对象,然后获取当前线程的ThreadLocalMap对象。
- ThreadLocalMap是以当前ThreadLocal对象为key,将值存储进ThreadLocalMap对象中的。
- 每一条线程均含有各自私有的ThreadLocalMap容器,因此不会存在线程安全性问题。
ThreadLocal使用示例
PS:ThreadLocal实例通常总是以静态字段初始化的。
/** * ThreadLocal测试类 * * @author 有梦想的肥宅 * @date 2021/9/6 */ public class ThreadLocalTest { public static void main(String[] args) throws Exception { MyThreadLocal myThreadTest1 = new MyThreadLocal(); myThreadTest1.setName("线程1"); ; myThreadTest1.start(); } } /** * 创建一个类,继承Thread,重写run方法 * * @author 有梦想的肥宅 */ class MyThreadLocal extends Thread { //1、创建一个threadLocal对象【PS:ThreadLocal实例通常总是以静态字段初始化的】 static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(); @Override public void run() { //2、在threadLocal中保存一个值 int num = (int) (Math.random() * 100D); threadLocal.set(num); //3、执行业务逻辑 Business business = new Business(); business.business(); } } /** * 模拟线程方法中调用的业务类 * * @author 有梦想的肥宅 */ class Business { //业务方法 public void business() { //模拟在业务代码中获取threadLocal的值 System.out.println(Thread.currentThread().getName() + "输出num:" + MyThreadLocal.threadLocal.get()); //清除 MyThreadLocal.threadLocal.remove(); } }
ThreadLocal的内存泄露问题
什么是内存泄露?
内存泄露指的是程序在申请内存后,无法释放已申请的内存空间。
产生原因
原因:在线程池中创建的线程,并设置了ThreadLocal。
解析:因为ThreadLocal的生命周期是跟随线程的,而线程池中的线程执行完任务后不会回收。虽然ThreadLocalMap中的key是弱引用,在GC时会被回收,但是其value却是强引用,是无法被回收的。所以如果我们需要使用ThreadLocal,一定要记得最后手动调用一下threadLocal.remove()方法,防止内存泄露。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律