StopWatch与ThreadLocal

目录

1、StopWatch

1、1作用:

1、2方法:

1、3使用方法

 2、ThreadLocal

2、1什么是ThreadLocal

2、2简单例子

2、3使用ThreadLocal带来的四个好处

2、4主要方法

2、5ThreadLocal内存泄漏问题


1、StopWatch

1、1作用:

 统计代码块耗时时间

1、2方法:

  • 构造器:可以使用无参数构造器,也可使用传入一个String类型的id,创建一个指定了id的StopWatch
  • start():可以不传入参数,开始一个无名称的任务的计时,也可以传入String类型的参数来开始指定任务名的任务计时
  • stop():停止当前任务的计时
  • isRunning():返回此stopWatch是否正在计时某任务
  • getTotalTimeMillis():返回所有任务的总体执行时间(毫秒单位)
  • getLastTaskTimeMillis():返回上一个任务的耗时(毫秒单位)
  • prettyPrint():优美地打印所有任务的详细耗时情况

1、3使用方法

引入依赖,Spring框架自带,可不引入

<!-- spring核心包 -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>${spring.version}</version>
</dependency>
public class StopWatchTest {
    // 用于模拟一些操作
    private static void doSomeThing() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("任务一");
        doSomeThing();
        stopWatch.stop();

        stopWatch.start("任务二");
        doSomeThing();
        stopWatch.stop();
        System.out.println("stopWatch.isRunning() = " + stopWatch.isRunning());
        System.out.println(stopWatch.prettyPrint());
        System.out.println("stopWatch.getTotalTimeMillis() = " + stopWatch.getTotalTimeMillis());
        System.out.println("stopWatch.getLastTaskTimeMillis() = " + stopWatch.getLastTaskTimeMillis());
    }

}

 2、ThreadLocal

2、1什么是ThreadLocal

ThreadLocal 叫做本地线程变量,ThreadLocal 中填充的的是当前线程的变量,该变量对其他线程而言是封闭且隔离的,ThreadLocal 为变量在每个线程中创建了一个副本,这样每个线程都可以访问自己内部的副本变量.

同一个ThreadLocal所包含的对象,在不同的Threa中有不同的副本,这里有几点需要注意:

  • 因为每个Thread内有自己的实例副本,且该副本只能由当前Thread使用,这也是ThreadLocal命名的由来。
  • 既然每个Thread都有自己的实例副本,且其他Thread不可访问,那就不存在多线程共享的问题

ThreadLocal提供了线程本地的实例,它与普通变量的区别在于:

  • 每个使用该变量的线程都会初始化一个完全独立的实例副本。
  • ThreadLocal变量通常被private static修饰。
  • 当一个线程结束时,它所使用的所有ThreadLocal相对的实例副本都可被回收。

ThreadLocal适用于每个线程需要自己独立的实例,且该实例需要在多个方法中被使用。即变量在线程间隔离,但是在方法和类间共享。

每个Thread对象都有一个ThreadLocalMap,每个ThreadLocalMap可以存储多个ThreadLocal

2、2简单例子

如果没有ThreadLocal,定义一个全局变量后,所有线程都更改的是同一个值

public class TestThread1 {
    //线程本地存储变量


    public static int n =0;
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {//启动三个线程
            Thread t = new Thread() {
                @Override
                public void run() {
                    add10ByThreadLocal();
                }
            };
            t.start();
        }
    }

    /**
     * 线程本地存储变量加 5
     */
    private static void add10ByThreadLocal() {
        for (int i = 0; i < 5; i++) {

            n += 1;
            System.out.println(Thread.currentThread().getName() + " n=" + n);
        }
    }
}

最终 值为15,还可能出现线程安全问题

package com.ljx.splearn;

public class TestThreadLocal {
	
	//线程本地存储变量
	private static final ThreadLocal<Integer> THREAD_LOCAL_NUM = new ThreadLocal<Integer>() {
		@Override
		protected Integer initialValue() {
			return 0;
		}
	};
 
	public static void main(String[] args) {
		for (int i = 0; i < 3; i++) {//启动三个线程
			Thread t = new Thread() {
				@Override
				public void run() {
					add10ByThreadLocal();
				}
			};
			t.start();
		}
	}
	
	/**
	 * 线程本地存储变量加 5
	 */
	private static void add10ByThreadLocal() {
		for (int i = 0; i < 5; i++) {
			Integer n = THREAD_LOCAL_NUM.get();
			n += 1;
			THREAD_LOCAL_NUM.set(n);
			System.out.println(Thread.currentThread().getName() + " : ThreadLocal num=" + n);
		}
	}
	
}

 

打印结果:启动了 3 个线程,每个线程最后都打印到 "ThreadLocal num=5",而不是 num 一直在累加直到值等于 15

经典的使用场景是为每个线程分配一个 JDBC 连接 Connection。这样就可以保证每个线程的都在各自的 Connection 上进行数据库的操作,不会出现 A 线程关了 B线程正在使用的 Connection; 还有 Session 管理 等问题。

还有比如一个请求中需要访问三个服务,三个服务需要在子线程中依次修改用户信息,通常从session中取到用户信息,然后给三个线程操作,这样会出现线程安全问题,需要用锁来保证

使用ThreadLocal后,每个线程都是独立的,互不影响

2、3使用ThreadLocal带来的四个好处

  • 不需要加锁,提高执行效率
  • 线程安全
  • 更高效地利用内存节省开销,上面例子中,相比于成千上万个任务,每个任务都新建一个SimpleDateFormat,显然用ThreadLocal可以节省内存和开销。
  • 免去传参的繁琐,不需要每次都传同样的参数,ThreadLocal使得代码耦合度更低,更优雅

2、4主要方法

  • initialValue()方法会返回当前线程对应的初始值,这是一个延迟加载的方法,只有在调用get()方法的时候才会触发。
  • 如果不重写initialValue()方法,这个方法会返回null,一般使用匿名内部类的方法重写initialValue()方法,以便在后续的使用中可以初始化副本对象。
  • 当线程第一次调用get()方法访问变量的时候,会调用initialValue()方法,除非线程先前调用了set()方法,在这种情况下,不会为线程调用本initialValue()
  • 通常,每个线程最多调用一次initialValue()方法,但如果已经调用一次remove()方法后,再调用get()方法,则可以再次调用initialValue(),相当于第一次调用get()

ThreadLocalMap 类是每个线程Thread类里面的变量,但ThreadLocalMap这个静态内部类定义在ThreadLocal类中

2、5ThreadLocal内存泄漏问题

ThreadLocalMap中的每个Entry都是一个对key弱引用,同时,每个 Entry 都包含了一个对value的强引用

正常情况下,当线程终止时,保存在ThreadLocalMap中的value也会被垃圾回收,因为没有任何强引用了,但是在项目中我们一般使用线程池,线程都是复用的,一般线程都不会结束,那么key对应的value就不会被回收

使用结束后及时调用remove()方法,删除对应的Entry对象,可以避免内存泄漏,所以使用完ThreadLocal之后,应该调用remove()方法。

可同步参考 ThreadLocal详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/53888.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue中使用axios发送请求时,后端同一个session获取不到值

问题描述&#xff1a; 在登录页面加载完成后通过axios请求后端验证码接口&#xff08;这时后端会生成一个session用于保存验证码数值&#xff09;&#xff0c;当输入完用户名、密码、验证码后请求登录接口&#xff0c;报错验证码输入错误&#xff0c;打印后端保存验证码的sessi…

【ArcGIS Pro二次开发】(54):三调名称转用地用海名称

三调地类和用地用海地类之间有点相似但并不一致。 在做规划时&#xff0c;拿到的三调&#xff0c;都需要将三调地类转换为用地用海地类&#xff0c;然后才能做后续的工作。 一般情况下&#xff0c;三调转用地用海存在【一对一&#xff0c;多对一和一对多】3种情况。 前2种情况…

11-3_Qt 5.9 C++开发指南_QSqlQuery的使用(QSqlQuery 是能执行任意 SQL 语句的类)

文章目录 1. QSqlQuery基本用法2. QSqlQueryModel和QSqlQuery联合使用2.1 可视化UI设计框架2.1.1主窗口的可视化UI设计框架2.1.2 对话框的可视化UI设计框架 2.2 数据表显示2.3 编辑记录对话框2.4 编辑记录2.5 插入记录2.6 删除记录2.7 记录遍历2.8 程序框架及源码2.8.1 程序整体…

【RabbitMQ】Linux系统服务器安装RabbitMQ

一、下载 首先应该下载erlang&#xff0c;rabbitmq运行需要有erland环境。 官网地址&#xff1a;https://www.erlang.org/downloads 下载rabbitmq 官网环境&#xff1a;https://www.rabbitmq.com/download.html 注意&#xff1a;el7对应centos7&#xff0c;el8对应centos8…

探索运营商渠道佣金数字化运营

当前全球经济增长放缓&#xff0c;行业竞争持续加剧已是常态&#xff0c;用户需求越发苛刻、经营成本不断上升。内忧外患&#xff0c;企业经营如何突围&#xff1f;越来越多的企业发现&#xff0c;融合数字化技术的IT解决方案为企业提供了一种解决问题的可能。 数字化运营可以帮…

B. Binary Cafe(二进制的妙用)

题目&#xff1a;Problem - B - Codeforces 总结&#xff1a; 对于该题最简单的方法为使用二进制的数表示状态 例如&#xff1a; 对于一个数7的二进制&#xff1a;111 它的每一位都可表示两种状态我们可以理解为取或者不取 对于7这个数字它可以表示一种状态即在三个位置都…

道本科技||全面建立国有企业合规管理体系

为全面深化国有企业法治建设&#xff0c;不断加强合规管理&#xff0c;防控合规风险&#xff0c;保障企业稳健发展&#xff0c;近日&#xff0c;市国资委印发《常州市市属国有企业合规管理办法&#xff08;试行&#xff09;》&#xff08;以下简称《办法》&#xff09;&#xf…

小研究 - JVM GC 对 IMS HSS 延迟分析(二)

用户归属服务器&#xff08;IMS HSS&#xff09;是下一代通信网&#xff08;NGN&#xff09;核心网络 IP 多媒体子系统&#xff08;IMS&#xff09;中的主要用户数据库。IMS HSS 中存储用户的配置文件&#xff0c;可执行用户的身份验证和授权&#xff0c;并提供对呼叫控制服务器…

【Matlab】判断点和多面体位置关系的两种方法实现

我的主页&#xff1a; 技术邻&#xff1a;小铭的ABAQUS学习的技术邻主页博客园 : HF_SO4的主页哔哩哔哩&#xff1a;小铭的ABAQUS学习的个人空间csdn&#xff1a;qgm1702 博客园文章链接&#xff1a; https://www.cnblogs.com/aksoam/p/17590039.html 分别是向量判别法&…

Azure pipeline自动化打包发布

pipeline自动化&#xff0c;提交代码后&#xff0c;就自动打包&#xff0c;打包成功后自动发布 第一步 pipeline提交代码后&#xff0c;自动打包。 1 在Repos,分支里选择要触发的分支&#xff0c;这里选择cn_china,对该分支设置分支策略 2 在生产验证中增加新的策略 3 在分支安…

【单机多卡】torch改造代码为DDP单机多卡分布式并行

torch分布式数据并行DDPtorch.nn.parallel.DistributedDataParallel代码修改记录。&#xff08;要求pytorch_version>1.0&#xff09; 目录 1.&#x1f344;&#x1f344;要修改的地方概览 2.✏️✏️初始化 3.✏️✏️设置当前进程GPU 4.✏️✏️设置sampler 5.✏️✏…

后端技术趋势指南|如何选择自己的技术方向

编程多条路&#xff0c;条条通罗马 后台大佬 后台路线都是面对后台服务器业务&#xff0c;比如web后台服务器&#xff0c;视频后台服务器&#xff0c;搜索后台服务器&#xff0c;游戏后台服务器&#xff0c;直播后台服务器&#xff0c;社交IM后台服务器等等&#xff0c;大部分…

Python基础入门教程(下)

目录 七、函数进阶 7.1、函数多返回值 7.2、函数多种传参方式 位置参数 关键字参数 缺省参数 不定长参数 位置传递 关键字传递 7.3、匿名函数 函数作为参数传递 lambda匿名函数 八、文件操作 8.1、文件的读取 open()打开函数 mode常用的三种基础访问模式 读操…

无人机调试笔记——常见参数

无人机的PID调试以及速度相关参数 1、Multicopter Position Control主要是用来设置无人机的各种速度和位置参数。调试顺序是先调试内环PID&#xff0c;也就是无人机的速度闭环控制&#xff0c;确认没有问题后再进行外环位置控制&#xff0c;也就是定点模式控制。 2、调试的时…

【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值

[导读]本系列博文内容链接如下&#xff1a; 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 【C】【C】做一个飞机空战小游戏(三)——模块化程设设计 最近想用c做一个小游戏&#x…

ClickHouse的安装启动

安装步骤 1.关闭防火墙 2.修改资源限制配置文件 2.1 路径&#xff1a;/etc/security/limits.conf 在末尾添加&#xff1a; * soft nofile 65536 #任何用户可以打开的最大的文件描述符数量&#xff0c;默认1024 这里的设置会限制tcp连接数 * hard nofile 65536 * soft nproc…

Android 测试

工程目录图 1- Espresso 2- uiautomator Espresso 文档UI Automator文档ui-automator 英文文档 请点击下面工程名称&#xff0c;跳转到代码的仓库页面&#xff0c;将工程 下载下来 Demo Code 里有详细的注释 代码&#xff1a;testespresso 参考文献 Android 利用 espre…

自建纯内网iot平台服务,软硬件服务器全栈实践

基于以下几个考虑&#xff0c;自制硬件设备&#xff0c;mqtt内网服务器。 1.米家app不稳定&#xff0c;逻辑在云端或xiaomi中枢网关只支持少部分在本地计算。 2.监控homeassistant官方服务有大量数据交互。可能与hass安装小米账户有关。 3.硬件&#xff1a;原理图&#xff0c;l…

机器学习李宏毅学习笔记39

文章目录 前言一、大模型的发展趋势二、KNN LM总结 前言 大模型大资料 大模型的顿悟时刻 一、大模型的发展趋势 随数据量增加&#xff0c;模型可以从量变达到质变&#xff0c;从某一刻开始突然学会东西。 当成为大模型时&#xff0c;分数会从0,0突然变成100&#xff0c;完成“…

OSG3.6.5 + VS2017前期准备及编译

OSG3.6.5 VS2017前期准备及编译 1、前期准备 1.1、osg稳定版本源码 Stable releases (openscenegraph.com) 1.2、osg依赖项 Dependencies (openscenegraph.com) 1.3、osg测试及演示数据 Data Resources (openscenegraph.com) 1.4、安装doxygen和Graphviz&#xff08;用…