JAVA多线程基础篇 8、线程隔离与ThreadLocal

TreadLocal实现线程之间数据隔离 在上面的代码中,我们首先创建出了一个ThreadLocal类型的roleLocal对象, 然后创建出两个不同的线程,在线程中先使用roleLocal分别保存不同的角色名称,然后调用show()方法通过roleLocal取出角色名称,再调用Sample的dosth()方法通过roleLocal取出角色名称。从运行结果看出,两个线程分别保存自己的角色名称,实现了线程之间的数据隔离,在show()方法和Sample类的dosth()方法之间,ThreadLocal实现了同一个线程中不同方法之间的数据传递。 阅读详情

在多线程并发环境中,要保证线程并发安全总体有2类方法。

  • 使用锁,在访问资源时是互斥的、原子性的。

    • 这个锁可以是Synchronized方法 或 Lock。
    • 或者CAS方式的乐观锁。
  • 使用线程隔离的方法。

    • 变量在线程内部,在实际运行过程中只有这个线程可以读取。

    • 变量在线程外部定义,但是每个线程只能操作属于该线程的变量副本。即 ThreadLocal类型的变量。

1. ThreadLocal的使用示例

定义了两个ThreadLocal类型的变量,线程t1设置的值,对于线程t2是不可见的。

public class ThreadLocalTest1 {
    private static ThreadLocal<String> thl1 = new ThreadLocal<>();
    private static ThreadLocal<Integer> thl2 = new ThreadLocal<>();

    public static void main(String[] args) {
        Thread t1 = new Thread(()->{
            thl1.set("abc");
            thl2.set(12);
            thl1.remove();
            thl2.remove();
            System.out.println(thl1.get()+","+ thl2.get());
        });

        Thread t2 = new Thread(()->{
            System.out.println(thl1.get()+","+ thl2.get());
        });

        t1.start();
        t2.start();
    }
}

运行结果:

ThreadLocal

2. ThreadLocal的使用场景

2.1 线程隔离的数据库连接与事务

定义一个数据库连接,每个线程拿到的数据库连接都是本线程对应的数据库连接。

public class ConnectionManager {

    private static final ThreadLocal<Connection> dbConnectionLocal = new ThreadLocal<Connection>() {
        @Override
        //初始化数据。
        //延迟调用方法,在线程第一次调用get或set时才执行,并且只执行1次。默认返回null。
        protected Connection initialValue() {
            try {
                return DriverManager.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    };

    public Connection getConnection() {
        return dbConnectionLocal.get();
    }
}

2.2 线程隔离的session会话

在每个线程session会话都是本线程对应的session。

private static final ThreadLocal threadSession = new ThreadLocal();  
  
public static Session getSession() {  
    Session s = (Session) threadSession.get();  
    try {  
        if (s == null) {  
            s = getSessionFactory().openSession();  
            threadSession.set(s);  
        }  
    } catch (Exception ex) {  
    }  
    return s;  
}  

3. ThreadLocal原理

  • Thread类内部定义了一个ThreadLocalMap 对象ThreadLocal.ThreadLocalMap threadLocals = null;当线程调用threadlocal对象的set(Object o)和get方法时,实际上是维护ThreadLocalMap对象。

    • 如果这个对象尚未初始化,则初始化
    • set时,以threadlocal对象为key,o 为value。
    • get时,以threadlocal对象为key取出value。
  • 举例说明:

    • thl1.set("abc");thl2.set(12);两条命令会在线程内的ThreadLocalMap对象上插入两条记录,这两条记录的key分别是thl1,thl2。值分别是"abc",12。
    • thl1.get(); thl2.get();命令执行时,实际上会在当前线程内的ThreadLocalMap对象上,查找key为thl1、thl2的值。
  • 也就是说,每个线程内部其实都有一个专属的“记录”——ThreadLocalMap,当写入和读取时,都会以threadlocal对象的引用为key,去存储读取。

4. ThreadLocal与内存泄露

内存泄露是指内存空间不可用,即使jvm进行垃圾回收也无法有效回收垃圾。

4.1 Java语言将Entry设计为弱引用

设想:当线程内对ThreadLocal对象使用方法完毕后,此时没有对象指向ThreadLocal对象,按理说这个对象可以被回收了。但是由于ThreadLocalMap里以key,value的形式存储了ThreadLocal对象。导致仍然有链接指向ThreadLocal对象,不能被回收。

因此,Java语言将Entry类设置为弱引用,当线程内对ThreadLocal对象使用方法完毕后,JVM可以在垃圾回收时,清除ThreadLocalMap内的无效Entry对象。

		static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }

4.2 记得手动remove

由于ThreadLocalMap的生命周期和Thread(当前线程)一样长。

尽管java语言做出了良好的设计,但是若当前线程一直不结束,又或者由于线程在线程池中,结束后不被销毁,那么ThreadLocal被回收后,ThreadLocalMap就会存在null,但value不为null的Entry。无效数据会移植存储在内存中,无法回收,导致内存泄露。

所以在使用完ThreadLocal对象后,要及时调用ThreadLocal.remove()方法,手动删除对应value。

总结

ThreadLocal的设计是为了能够在当前线程中有属于自己的变量,其原理是每个线程内部其实都存储了一个ThreadLocalMap来记录保存。ThreadLocal对象存在内存泄露的风险,需要手工remove。

多线程系列在github上有一个开源项目,主要是本系列博客的实验代码。

https://github.com/forestnlp/concurrentlab

如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。

您的支持是对我最大的鼓励。

什么是ThreadLocal,一篇文章彻底搞懂Java多线程中的ThreadLocal【保姆级教程】 多线程、Thread、java 阅读详情

相关推荐

多线程间共享变量线程安全问题——ThreadLocal

ThreadLocal 的作用,可以实现在同一个线程数据共享, 从而解决多线程数据安全问题.ThreadLocal 可以给当前线程关联一个数据(普通变量、 对象、 数组)set 方法 [源码!]ThreadLocal 可以像 Map 一样存取数据, key 为当前线程, get 方法每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数 据, 就需要使用多个 ThreadLocal对象实例。

ywl470812087的博客 2465

Java多线程(四)——多线程数据隔离与共享

  目录 一、引言 二、数据隔离 三、数据共享 1、传入Runnable赋值成员变量 2、新建外部类添加成员变量(这个是教程3中用到的,我比较常用) 四、总结   一、引言   多线程数据隔离与数据共享是个矛盾体,有些数据需要隔离,比如每个人的银行账户,有些需要共享比如买票的总火车票数量,这个问题导致了这篇文章的出现,抽象出了这两类问题。     二、数据隔离   ...

xcymorningsun的专栏 4920

多线程之线程范围内的数据共享ThreadLocal

如果多个线程使用同一个数据,那么如何保证线程范围内的数据共享。 我们可以使用一个map来存储当前线程,以及其数据如下: package andy.thread.traditional.test; import java.util.HashMap; import java.util.Map; import java.util.Random; /** * @author Zhang,Tian

Andyの笔记 1684

Java 入门指南:Java 并发编程 —— 线程隔离技术 ThreadLocal

线程隔离是一种多线程编程技术,它可以将数据或资源在不同线程之间进行隔离,保证每个线程使用的数据或资源是独立的,不会互相干扰。线程隔离通常应用于高并发场景下,可以有效提升系统性能并提高并发能力。

热带鱼的技术博客 2554

【Java 多线程 3】理解ThreadLocal

一、基本介绍 经过一宿的面壁思过,下文写的对ThreadLocal的源码分析,过于枯燥乏味,现在简单的总结一下ThreadLocal,提高一下做人的level。 ThreadLocal的作用就是:线程安全。 ThreadLocal的本质就是一个内部的静态的map,key是当前线程的句柄,value是需要保持的值。 由于是内部静态map,不提供遍历和查询的接口,每个线程只能获取自己线程的value。 这样,就线程安全了,又提供了数据共享的能力,perfect。 二、ThreadLocal的应用

学Java,找哪吒 5986

Java并发_第九篇:线程隔离,ThreadLocal之诞生

文章目录一、前言二、定义与用法2.1 定义2.2 用法三、源码分析3.1 主干方法,给开发者使用:set()方法3.1.1 set()方法解读3.1.2 继续深入set(ThreadLocal<?> key, Object value)3.1.3 继续深入,threadLocalHashCode变量3.2 主干方法,给开发者使用:get()3.2.1 源码解析:get()3.2.2 继续深入getEntry()方法3.2.3 继续深入,getEntryAfterMiss()方法3.3 主干方法,

毛毛的专栏 821

面经-并发-对ThreadLocal(线程隔离)的理解

ThreadLocal作用: 1.线程隔离。线程间:ThreadLocal可实现资源对象的线程隔离,让每个线程各用各的资源对象,避免争用引发的线程安全问题。 2.资源共享。线程内:ThreadLocal同时实现了线程内的资源共享。 ThreadLocal原理:关联资源 每个线程中都有一个独立的ThreadLocalMap类型的成员变量,用来存储资源对象。 1.调用set方法,就以ThreadLo...

LYly_B的博客 517

2023电赛B题实战解析:基于立创天空星开发板的同轴线缆长度与负载测量系统

本文详细解析了2023年全国大学生电子设计竞赛B题的实战方案,重点介绍了基于立创EDA天空星开发板(STM32F103)的同轴线缆长度与负载测量系统。文章深入剖析了两种核心测量方案,并推荐了更稳定易实现的NE555测电容法,提供了从硬件选型、电路设计到软件编程、参数标定的完整“施工图”,实测精度可达厘米级和皮法级,为电赛复现与高精度测量学习提供了清晰指导。

weixin_36303305的博客 232

利用ThreadLocal保存登录Session信息

ThreadLocal(线程本地变量)通常理解为“采用了空间换时间的设计思想,主要用来实现在多线程环境下的线程安全和保存线程上下文中的变量”。在实际的项目开发中(比如2C APP程序的服务器端程序),通常在APP调用服务端API接口的时候,需要token(登录)验证并且在具体的方法中可能会使用到当前登录账户的更多信息(比如当前登录账户的用户ID)。以前的做法,我们喜欢把(通过token获取)用户登...

点滴成长 9541

DDSP(Differentiable Digital Signal Processing) 开篇

文章目录DDSP可以用来做什么?下一步工作 工作中接触到了DDSP声码器,但非科班出声的我对这块知识非常陌生,甚至带有一些畏惧的心理,但是为了工作为了进步,必须硬下头皮去啃,相信只要耐心地坚持,没什么能难到我。于是从今天开始,就用这个博客专栏来记录我的学习历程,希望也能帮助到你~ DDSP对应的论文是:DDSP: Differentiable Digital Signal Processing 先翻译一篇来自DDSP论文作者的对DDSP的介绍的文章。 今天,我们很高兴地介绍可微数字信号处理(DDSP)库。

YeeKo的博客 9246

GaN制备micro-led(一)

随着第三代半导体 GaN 材料的快速发展,GaN 基 LED 发展迅速并广泛商业化,这 为可见光通信的实现及应用提供了基础。然而,普通商用 LED 的调制带宽只有几十兆 赫兹,并不能很好的满足可见光通信系统高传播速率的需求。为增大调制带宽,针对发 射端 LED 光源部分的改进仍需提高。将光子晶体结构引入 LED 芯片量子阱内部,能够 影响光子寿命和光子传播,进而改变 LED 芯片的调制带宽和光提取效率。结合倒装微 尺寸(Micro)LED 结构,使其封装体积最小化,这使得可见光通信能够更加灵活地.

weixin_45852211的博客 896

Java多线程基础知识总结

<-----------------------------------------廖雪峰学Java-----------------------------------------> 目录1. 多线程基础知识2. 创建多线程3. 线程状态4. 中断线程5. 守护线程6. 线程同步7. 同步方法8. 死锁9. 使用wait和notify10. 使用ReentrantLock11. 使用Condition12. 使用ReadWriteLock13. 使用StampedLock14. 使用Concu

Pinkgranite86的博客 2721

Ollama系列---【ollama使用gpu运行大模型】

一、安装CudaToolkit 使用控制台命令查看当前显卡驱动中的cuda版本 nvidia-smi 二、下载CudaToolkit 注意:CudaToolkit版本要低于上面的显卡Cuda版本。 Cuda各版本下载地址:https://developer.nvidia.com/cuda-toolkit-archive 下载好之后,一路下一步,一直默认即可。 如果安装到了自定义的位置,记得加环...

-少年-的博客 7982

JAVA多线程基础篇-类ThreadLocal

ThreadLocal类是JDK1.2中提供的一个类,它是解决多线程并发程序的一个类。它能够提供线程内的局部变量,使得不同线程之间变量不会相互干扰,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数组件之间一些公共变量传递的复杂度。在大部分场景下,使用ThreadLocal比直接使用synchronized解决线程安全问题更简单和方便,本文将探索ThreadLocal的具体使用方式和底层原理。.................................

qq_33479841的博客 988

基于YOLOv8的人群聚集检测系统:含UI界面设计与数据集应用

人群聚集检测是智慧城市、公共安全和疫情防控等领域的重要任务。本文结合YOLOv8最新目标检测技术,设计并实现了一个高效的人群聚集检测系统,支持可视化UI界面操作,方便用户实时检测和分析视频中的人群密度。本文详细介绍了系统设计思路、使用的数据集、YOLOv8模型训练和推理过程,以及UI界面的开发与整合。最后通过实验验证了该系统的实用性和性能表现。更灵活的模型架构强化的特征融合网络(PAN++)自动混合精度训练支持支持多任务学习(目标检测+分类+分割)预训练模型丰富,适应多种应用场景。

YOLO 433

全志V3S嵌入式驱动开发(编译器升级到7.5)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 看过我们文章的朋友都知道,前面为了做v3s的驱动,对linux kernel进行了两次升级。第一次升级时从4.10.y升级到4.14.y,另外一次升级是从4.14.y升级到5.2.y。这中间最主要的原因,就是为了驱动适配的需要,更新的内核可以对硬件驱动有更好的支持,架构也更合理。 如果说内核升级尚且可以理解,那为什么要对编译器升级呢?这里面,最重要的一点就是语言的升

嵌入式-老费,一个分享专业嵌入式知识的blog 1166

多线程中ThreadLocal的使用

前言 多线程是Java的一个重要特性,多线程从某方面可以等价于多任务,当你有多个任务要处理时,多个任务一起做所消耗的时间肯定比任务串行起来做,所消耗的时间短。而对于多线程不熟悉的新手则容易踩到很多坑,最典型的则是变量问题。 概念介绍 下面先用简单粗俗的语言解释一下几个基本概念 线程安全:多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读...

qq_36403693的博客 1213

GibbsCAM软件二次开发:GibbsCAM软件API接口详解

API(Application Programming Interface,应用程序编程接口)是一种允许不同软件之间进行通信的接口。在GibbsCAM软件中,API提供了与外部程序交互的能力,使得开发者可以利用GibbsCAM的强大功能进行二次开发,定制化满足特定的制造需求。GibbsCAM的API主要基于.NET框架,使用C#或VB.NET等语言进行编程。在GibbsCAM软件中,通过API接口创建自定义几何形状是实现复杂零件设计和加工策略定制的关键步骤。

kkchenjj的博客 1497

Java 多线程之 ThreadLocal 的使用

ThreadLocal 用于在多线程环境中维护线程封闭(thread-local)的变量。线程封闭是一种确保变量在多线程环境中的线程安全性的机制,每个线程都有自己独立的变量副本,互不干扰。ThreadLocal 提供了一种简单的方式来实现线程封闭,它为每个线程都创建了一个独立的变量副本。使用场景保存线程私有数据:当多个线程需要访问某个数据,但每个线程都需要有自己的数据副本时,可以使用 ThreadLocal。

QIFU的专栏 1668

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Java多线程,ThreadLocal,锁,Synchronized的理解

想象一下,开了一家餐厅(服务器)(Process)=整个餐厅,如果餐厅倒闭了=进程结束了,里面的东西都没了(Thread)=厨师。单线程就是一个厨师干店里面活,多线程就是多个厨师干店里面的活。

2301_76506734的博客 432

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Java多线程编程-(10)-看了这篇关于ThreadLocal的原理应该透彻了

Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁代码谈一下volatile关键字 Java多线程编程-(4)-线程本地ThreadLocal的介绍与使用 Java多线程编程-(5)-线程间通信机制的介绍与使用 Java

Java后端技术 1345

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Java多线程基础-ThreadLocal

感谢原文作者:Yuicon 原文链接:https://segmentfault.com/a/1190000016705955 序 在多线程环境下,访问非线程安全的变量时必须进行线程同步,例如使用synchronized方式访问HashMap实例。但是同步访问会降低并发性,影响系统性能。这时候就可以用空间换时间,如果我们给每个线程都分配一个独立的变量,就可以用非同步的方式使用非线程安全的变量,...

Jason的学习笔记 275

Java 中的 ThreadLocal

ThreadLocal 是一个强大的工具,可以有效地解决多线程编程中的数据隔离问题,但也需要谨慎使用,以避免潜在的内存泄漏风险。通过合理的使用和管理,可以在高并发环境下提高程序的性能和稳定性。

weixin_43016432的博客 1116

(Java多线程常见面试题)ThreadLocal 是什么?有哪些使⽤场景?

ThreadLocal Java多线程 java面试题

东东先生的博客 984
上一篇: 一遍就能懂的UML
下一篇: JAVA多线程进阶篇 10、JUC之Callable Future FutureTask
悟空学编程
博客等级 码龄12年 32粉丝 123原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟空学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值