在特定情况,我们希望这样一个场景:

N个线程同时调用同一个类实例的同一个操作方法,并且同一个变量可以面向每一个线程存储独立的值。比如,某变量X,它对于线程A的值与对于线程B的值是相互独立的。线程A设置了X的值为3,那么只要代码是在线程A上执行的,那么变量X的值就是3;线程B设置X值为7,那么在线程B的代码中X的值就为7。

同样一个X变量,不同的线程访问它就会读写不同的值

有些时候,我们需要以上功能。只要把希望基于线程本地所使用的值的变量类型声明为ThreadLocal<T>类型即可,其中T表示该变量中要存储的值的数据类型。

下面定义一个类:

    public sealed class ThreadingWork
{
private Random m_rand = null;
private ThreadLocal<int> m_localVal = default(ThreadLocal<int>); public ThreadingWork()
{
m_rand = new Random();
m_localVal = new ThreadLocal<int>();
} private void MakeRandom()
{
m_localVal.Value = m_rand.Next(, );
} public void RunOnThreads()
{
// 为变量生成值
MakeRandom();
// 引发事件
string str = $"在线程{Thread.CurrentThread.ManagedThreadId}上设置的值为:{m_localVal.Value}";
ThreadingRuned?.Invoke(this, new RunThreadEventArgs(str));
} public event EventHandler<RunThreadEventArgs> ThreadingRuned; } /// <summary>
/// 自定义事件参数类
/// </summary>
public class RunThreadEventArgs : EventArgs
{
internal RunThreadEventArgs(string s)
{
Value = s;
} public string Value { get; private set; }
}

m_localVal变量是类的字段,它里面存放的是int类型的值。RunOnThreads方法会被不同的线程调用,线程执行方法后,会生成一个随机整数,并存到m_localVal变量中。接着引发ThreadingRuned事件,并将m_localVal变量中存放的值随着事件传递,以便被其他代码使用。

下面,我们测试一下。

            // 实例化对象
ThreadingWork work = new ThreadingWork();
// 附加事件处理
work.ThreadingRuned += Work_ThreadingRuned;
// 创建30个Task来干活
for(int n = ; n < ; n++)
{
Thread t = new Thread(work.RunOnThreads);
t.Start();
}

上面代码创建了30个线程,并且线程所执行的都是同一个实例work上的RunOnThreads方法。

当代码运行后,见证奇迹的一刻到了。

从运行结果中可以发现,同一个实例方法被多个线程调用,但m_localVal变量可以存放来自各个线程的值,而每个线程所读取的都是基于当前线程的值,即每个线程读写的值都不同。

尤其是在实现多线程下载的案例中,可以使用同一个实例变量来记录源自不同线程的下载进度(假设每个线程开启一个下载任务)。

例子代码下载

【.NET深呼吸】存储基于本地线程的值的更多相关文章

  1. 3、flask之基于DBUtils实现数据库连接池、本地线程、上下文

    本篇导航: 数据库连接池 本地线程 上下文管理 面向对象部分知识点解析 1.子类继承父类__init__的三种方式 class Dog(Animal): #子类 派生类 def __init__(se ...

  2. flask之基于DBUtils实现数据库连接池、本地线程、上下文

    本篇导航: 数据库连接池 本地线程 上下文管理 面向对象部分知识点解析 1.子类继承父类__init__的三种方式 class Dog(Animal): #子类 派生类 def __init__(se ...

  3. Python 本地线程

    1. 本地线程,保证即使是多个线程,自己的值也是互相隔离. 2.普通对象演示 import threading import time class A(): pass a=A() def func(n ...

  4. 基于本地存储的kvm虚拟机在线迁移

    基于本地存储的kvm虚拟机在线迁移 kvm虚拟机迁移分为4种(1)热迁移基于共享存储(2)热迁移基于本地存储(3)冷迁移基于共享存储(4)冷迁移基于本地存储 这里介绍的是基于本地存储的热迁移 动态块迁 ...

  5. [Swift]LeetCode981. 基于时间的键值存储 | Time Based Key-Value Store

    Create a timebased key-value store class TimeMap, that supports two operations. 1. set(string key, s ...

  6. LeetCode 981.基于时间的键值存储(C++)

    创建一个基于时间的键值存储类 TimeMap,它支持下面两个操作: 1. set(string key, string value, int timestamp) 存储键 key.值 value,以及 ...

  7. ThreadLocal = 本地线程?

    一.定义 ThreadLocal是JDK包提供的,从名字来看,ThreadLocal意思就是本地线程的意思. 1.1 是什么? 要想知道他是个啥,我们看看ThreadLocal的源码(基于JDK 1. ...

  8. Java 类 ThreadLocal 本地线程变量

    前言:工作中将要使用ThreadLocal,先学习总结一波.有不对的地方欢迎评论指出. 定义 ThreadLocal并不是一个Thread,而是Thread的局部变量.这些变量不同于它们的普通对应物, ...

  9. [How to]基于本地镜像的yum镜像源搭建

    1.简介 本文介绍如何在封闭环境(无外网)下安装离线安装本地镜像与基于本地镜像的yum镜像源. 2.环境版本交代: OS:CentOS-6.7-x86_64-minimal yum: yum-3.2. ...

随机推荐

  1. Codeforces Round #345 (Div. 1) A. Watchmen

    A. Watchmen time limit per test 3 seconds memory limit per test 256 megabytes input standard input o ...

  2. CentOS 6.4下编译安装MySQL 5.6.14

    概述: CentOS 6.4下通过yum安装的MySQL是5.1版的,比较老,所以就想通过源代码安装高版本的5.6.14. 正文: 一:卸载旧版本 使用下面的命令检查是否安装有MySQL Server ...

  3. Java 实现HTML富文本导出至word完美解决方案

    一. 问题的提出 最近用java开发一个科技项目信息管理系统,里面有一个根据项目申请书的模板填写项目申报信息的功能,有一个科技项目申请书word导出功能. 已有的实现方式:采用标准的jsp模板输出实现 ...

  4. Rust语言的多线程编程

    我写这篇短文的时候,正值Rust1.0发布不久,严格来说这是一门兼具C语言的执行效率和Java的开发效率的强大语言,它的所有权机制竟然让你无法写出线程不安全的代码,它是一门可以用来写操作系统的系统级语 ...

  5. Ubuntu Java 环境变量

    方法1:修改/etc/profile 文件所有用户的 shell都有权使用这些环境变量<1>在 shell终端执行命令:vi /etc/profile<2>在 profile文 ...

  6. spark 大数据 LR测试

    #!/bin/bash size="120Y*10W"date1=`date +%F_%H-%M-%S`config="spark-submit \ --jars /da ...

  7. java.net.ConnectException: Connection timed out

    原因可能如下: (1)生成的WSDL的IP地址是不是服务器的IP: (2)代码中是否需要代理,若否,取消代理,若是,设置代理:

  8. 2016huasacm暑假集训训练五 E - What Is Your Grade?

    题目链接:http://acm.hust.edu.cn/vjudge/contest/126708#problem/E 题意:给做出的题目个数,5个的100分,4个的前n/2的同学95,后n/2的90 ...

  9. Android课程---关于数据存储的学习之总结

  10. Java实现文件在某个目录的检索

    package com.filetest; import java.io.File; import java.util.Date; import java.util.Scanner; public c ...