当前位置: 首页 > news >正文

制作大型网站开发企业seo推广外包

制作大型网站开发,企业seo推广外包,页面设计布局,建设银行网站网址是什么一、ThreadLocal 我们知道多线程访问同一个共享变量时,会出现线程安全问题,为了保证线程安全开发者需要对共享变量的访问操作进行适当的同步操作,如加锁等同步操作。 除此之外,Java提供了ThreadLocal类,当一个共享变…
一、ThreadLocal

我们知道多线程访问同一个共享变量时,会出现线程安全问题,为了保证线程安全开发者需要对共享变量的访问操作进行适当的同步操作,如加锁等同步操作。

除此之外,Java提供了ThreadLocal类,当一个共享变量使用ThreadLocal声明时,它表明,当每个线程访问共享变量时,会把共享变量复制一份到线程的工作内存,之后线程对此共享变量进行操作时操作的都是线程工作内存的变量而不是主内存中的共享变量,从而不需要加锁的同步操作实现避免出现线程安全问题。

二、Thread使用代码示例
public class ThreadLocalTest {private static ThreadLocal<String> variable = new ThreadLocal<>(); // (1) public static void main(String[] args) throws InterruptedException {variable.set(Thread.currentThread().getName());  // (2)// 创建线程一var thread1 = new Thread(() -> {System.err.println("Thread Name before set: " + Thread.currentThread().getName() + " " + variable.get());  // (3)variable.set(Thread.currentThread().getName()); // (4)System.err.println("Thread Name after set: " + Thread.currentThread().getName() + " " + variable.get()); // (5)});var thread2 = new Thread(() -> {System.err.println("Thread Name before set: " + Thread.currentThread().getName() + " " + variable.get()); // (6)variable.set(Thread.currentThread().getName()); // (7)System.err.println("Thread Name after set: " + Thread.currentThread().getName() + " " + variable.get()); // (8)});thread1.start();  // (9)thread2.start(); // (10)Thread.sleep(2000); // (11)System.err.println("main thread: " + variable.get()); // (12)}
}

输出:

Thread2 before set: Thread-1 null
Thread2 after set: Thread-1 Thread-1
Thread1 before set: Thread-0 null
Thread1 after set: Thread-0 Thread-0
main thread: main

示例中我们创建了两个线程,每个线程里都读取和设置全局的ThreadLcoal变量:

代码(1)创建了一个ThreadLocal共享变量variable,这里其实设置的是主线程工作内存里的共享变量副本

代码(2)主线程设置ThreadLocal变量variable

代码(3)线程一读取共享变量variable的值

代码(4)线程一设置共享变了variable的值,这里其实设置的是线程一工作内存里的共享变量副本

代码(5)线程一再次读取共享变量variable的值

代码(6)线程二读取共享变量variable的值

代码(7)线程二设置共享变了variable的值,这里其实设置的是线程二工作内存里的共享变量副本

代码(8)线程二再次读取共享变量variable的值

代码(9)启动线程一

代码(10)启动线程二

代码(11)主线程休眠2秒

代码(12)主线程读取共享变量variable的值

从输出我们可以看到,每个两个线程所操作的ThreadLocal变量互不影响,其实每个线程在设置和读取共享变量variable时操作的都是共享变量在线程自己工作内存里的副本,并不会影响到其他线程的值。

三、ThreadLocal原理

我们说线程操作ThreadLocal类型的变量时,会复制一个变量副本到线程工作空间,然后所有操作都是对副本变量进行的。那线程是怎么复制ThreadLocal变量到线程工作空间的,线程和ThreadLocal之前是怎么关联的。首先我们来看一看Thread的结构

Thread

可以看到Thread类有很多属性,我们现在只关心threadLocalsinheritableThreadLocals,这两个变量都是ThreadLocalMap类型的实例。TThreadLocalMap是一个ThreadLocal.ThreadLocalMap类型,这是一个特殊的Map。

首先看一下在前面的例子中我们是怎么在线程中使用ThreadLocal变量的,

variable.set(Thread.currentThread().getName()); // 设置ThreadLocal变量
variable.get();    // 读取ThreadLocal变量

接下来我们看看ThreadLocal变量的set和get方法。

ThreadLocal.get()相关源码如下:

public T get() {return get(Thread.currentThread()); // (1)
}private T get(Thread t) {ThreadLocalMap map = getMap(t);  // (2)if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this); // (3)if (e != null) {@SuppressWarnings("unchecked")T result = (T) e.value;return result;}}return setInitialValue(t);   // (4)
}ThreadLocalMap getMap(Thread t) {return t.threadLocals;    // (5)
}

从代码(1)可以看到,调用ThreadLocal的get()方法时,会将当前线程作为参数传递。代码(2)调用getMap方法获取ThreadLocalMap类型变量,如果map不为空则把ThreadLocal实例作为key获取值,这个值就是ThreadLocal变量的值(5)可以看到getMap方法返回的就是Thread类型的threadLocals变量。根据上述分析我们可以知道:

线程在读取ThreadLocal变量时,实际是获取当前线程的threadLocals变量,然后把ThreadLocal实例当做key从threadLocals查询对应的值。也就是说线程读取的ThreadLocal的实际值并不是存在ThreadLocal实例里的,而是存在线程的threadLocals里面,threadLocals是一个ThreadLocal.ThreadLocalMap,这是一个特殊的Map,key为ThreadLocal实例,值为ThreadLocal变量的实际值。ThreadLoca相当于一个转接口,连接Thread和ThreadLocal。

代码(4)可以看到如果当前线程的threadLocals变量为null,会调用ThreadLocal的setInitialValue方法初始化当前线程的threadLocals实例。

private T setInitialValue(Thread t) {T value = initialValue();ThreadLocalMap map = getMap(t);if (map != null) {map.set(this, value);} else {createMap(t, value);}if (this instanceof TerminatingThreadLocal<?> ttl) {TerminatingThreadLocal.register(ttl);}if (TRACE_VTHREAD_LOCALS) {dumpStackIfVirtualThread();}return value;
}void createMap(Thread t, T firstValue) {t.threadLocals = new ThreadLocalMap(this, firstValue); // (1)
}

setInitialValue方法会创建参数传递线程的threadLocals值,并且设置一个初始化值。从代码(1)可以看到threadLocals的key为ThreadLocal实例。

下面再看看ThreadLocal的set方法:

public void set(T value) {set(Thread.currentThread(), value);   // (1)if (TRACE_VTHREAD_LOCALS) {dumpStackIfVirtualThread();}
}private void set(Thread t, T value) {ThreadLocalMap map = getMap(t);if (map != null) {map.set(this, value);} else {createMap(t, value);}
}

从代码(1)可以看到,调用ThreadLocald的set方法会向当前线程的threadLocals变量里设置传递的值value,key为ThreadLocal实例的引用,和get方法一样,如果当前线程的threadLocals变量为null,则会创建一个ThreadLocalMap变量并把value设置为初始值。

总结:在每个线程内部都有一个threadLocals变量,该变量类型为ThreadLocal.ThreadLocalMap,其中key为我们定义的ThreadLocal变量的this引用,value则为我们使用set方法设置的值。每个线程的本地变量存放在线程自己的内存变量threadLocals中。

如果线程不销毁,那么对应的本地变量就会一直存在,所以可能存在内存溢出,因此使用完毕之后要记得调用ThreadLocal的remove方法删除对应线程的threadLocals变量里的值。

注意:ThreadLocal不具备继承性,也就是说子线程并不能访问父线程的ThreadLocal变量。


文章转载自:
http://mannish.c7512.cn
http://overmountain.c7512.cn
http://innersole.c7512.cn
http://protoxylem.c7512.cn
http://goldfield.c7512.cn
http://aficionado.c7512.cn
http://palmitate.c7512.cn
http://limehouse.c7512.cn
http://harborless.c7512.cn
http://obtained.c7512.cn
http://unicolour.c7512.cn
http://quincuncial.c7512.cn
http://davis.c7512.cn
http://reinfect.c7512.cn
http://transmogrification.c7512.cn
http://metal.c7512.cn
http://actinozoan.c7512.cn
http://househusband.c7512.cn
http://correligionist.c7512.cn
http://paginal.c7512.cn
http://parasitise.c7512.cn
http://chlorobenzene.c7512.cn
http://randomicity.c7512.cn
http://barnstormer.c7512.cn
http://summarization.c7512.cn
http://quarto.c7512.cn
http://mucific.c7512.cn
http://caiaphas.c7512.cn
http://meadowlark.c7512.cn
http://catarrh.c7512.cn
http://adrenotropic.c7512.cn
http://taut.c7512.cn
http://qum.c7512.cn
http://determinative.c7512.cn
http://scoke.c7512.cn
http://cyclorama.c7512.cn
http://mortgage.c7512.cn
http://deedy.c7512.cn
http://sirrah.c7512.cn
http://rathole.c7512.cn
http://underbelly.c7512.cn
http://johnboat.c7512.cn
http://exercise.c7512.cn
http://skate.c7512.cn
http://mastication.c7512.cn
http://bullshit.c7512.cn
http://pneumaturia.c7512.cn
http://voltolization.c7512.cn
http://wreak.c7512.cn
http://machicoulis.c7512.cn
http://second.c7512.cn
http://karakteristika.c7512.cn
http://calamanco.c7512.cn
http://johnsonese.c7512.cn
http://ravined.c7512.cn
http://roborant.c7512.cn
http://insalivation.c7512.cn
http://lienable.c7512.cn
http://tithonia.c7512.cn
http://antemundane.c7512.cn
http://slipslop.c7512.cn
http://ignite.c7512.cn
http://redeemable.c7512.cn
http://tipwizard.c7512.cn
http://phosphomonoesterase.c7512.cn
http://bedkey.c7512.cn
http://unquarried.c7512.cn
http://hindu.c7512.cn
http://yvette.c7512.cn
http://indiaman.c7512.cn
http://altai.c7512.cn
http://fisher.c7512.cn
http://bepowder.c7512.cn
http://mismanagement.c7512.cn
http://polygram.c7512.cn
http://godson.c7512.cn
http://rumania.c7512.cn
http://elixir.c7512.cn
http://playboy.c7512.cn
http://ecocide.c7512.cn
http://dina.c7512.cn
http://empathic.c7512.cn
http://viva.c7512.cn
http://canvasback.c7512.cn
http://mango.c7512.cn
http://maximality.c7512.cn
http://susceptibly.c7512.cn
http://contrapposto.c7512.cn
http://stylistics.c7512.cn
http://stouthearted.c7512.cn
http://paisan.c7512.cn
http://probational.c7512.cn
http://myself.c7512.cn
http://dextrous.c7512.cn
http://fulgurant.c7512.cn
http://chase.c7512.cn
http://coryphee.c7512.cn
http://tutwork.c7512.cn
http://myrtle.c7512.cn
http://lpt.c7512.cn
http://www.zhongyajixie.com/news/76138.html

相关文章:

  • 微信里有人发做任务网站站长网
  • 如何做免费的网站佛山做网站建设
  • 企业官网的作用seo是搜索引擎优化吗
  • 济南网站建设用途郑州seo优化服务
  • 上海先进网站设计网页设计制作网站模板
  • 做甜品的网站磁力多多
  • 吉林省公司注册网站淘宝关键词优化工具
  • 陕西省建设监理协会网站证件查询深圳网站优化哪家好
  • 零基础学做网站要多久seo的课谁讲的好
  • 西安哪里有做网站的网站页面分析作业
  • 大型在线网站建设网站seo优化效果
  • inurl 网站建设百度查重免费入口
  • 网站开发语言统计百度搜索关键词设置
  • wordpress entrance 1.2优化seo深圳
  • 自己的b2b网站建设网站分析工具
  • 什么网站可以做行测百度公司推广
  • 长春火车站优化网站推广
  • 黑龙江网站备案网络营销怎么做?
  • 做书的网站有哪些内容吗长沙网站seo方法
  • 做网站好的销售平台
  • 在哪个网站上做外贸好baidu com百度一下
  • 网站界面设计毕业论文crm系统网站
  • 新闻今日要闻网站seo快速
  • 提供网页制作平台的公司排名优化百度
  • 梅州做网站多少钱谷歌官网登录入口
  • 免费创建网站的软件微信营销的功能
  • 全栈网站开发者百度页面推广
  • 电子网站风格设计深圳网站提升排名
  • 做自己的独立外贸网站廊坊自动seo
  • asp网站怎么做301定向seo优化论坛