勤学教育网合作机构>石家庄培训>

石家庄兄弟连教育

欢迎您!

全国统一学习专线 8:30-21:00
石家庄兄弟连教育

石家庄兄弟连分层次分阶段的学习,由浅入深,根据学员的不同层次因材施教,授课中使用的案例都是真实的案例

石家庄兄弟连教育> 石家庄教育培训>

石家庄学java

  • 课程介绍

  • 相关知识

  • 2019-11-18
石家庄兄弟连java培训

Java在金融服务业的应用非常广泛,很多第三方交易系统、银行、金融机构都选择用Java开发,因为相对而言,Java较安全。大型跨国投资银行用Java来编写前台和后台的电子交易系统,结算和确认系统,数据处理项目以及其他项目。大多数情况下,Java被用在服务器端开发,但多数没有任何前端,它们通常是从一个服务器(上一级)接收数据,处理后发向另一个处理系统(下一级处理)。

石家庄兄弟连课程体系




java发展前景  Java发展前景  
计算机的诞生及广泛应用推动了IT领域的发展,但21世纪的计算机早已不是访问INTERNET的的途径。各类更具信息化的电子产品逐渐进入IT领域,推动了PC时代的大发展。由于各种消费信息的急剧增加,传统的客户机的各方面条件均不如PC,PC的发展对服务器的应用管理体统也提出了更高标准。Java语言完全满足了PC的条件,在减少内存,直接在各类电子产品中运行,在网络中可被任何设备所识别,充分利用网络资源等方面有所突破创新,为PC时代的发展创造了有力条件。
 

大咖教学天团,课程体系引领IT革新
他们曾经敲过的代码现如今已是业界标杆,是中国互联网的参与者与见证者!

  • 马如忠 马如忠 icon

    精通Java、C、C++等主流开发语言,5年以上开发经验,非常丰富的IT从业经验和教育心得,兄弟连特色JAVA讲师,曾担任达内课程总监级讲师。

  • 李康 李康 icon

    曾任用友软件,飞企集团等上市公司技术总监,CTO等职务,12年以上的软件开发和项目管理经验,领导并参与研发中国移动ERP终端系统。


兄弟连教育(以下简称兄弟连)致力于高素质软件开发人才的培训与培养。公司成立于2007年,总部设在北京,目前已在上海、广州、深圳、郑州、沈阳、成都、南京、杭州、宁波、石家庄、南昌等城市设立了教学中心,业务范围覆盖全国。2016年5月获得华图教育1.25亿元投资,同年9月挂牌新三板。


体验才是王道
高起点才更牛叉
缔造Java课程行业新标准
 
 

详情请进入 石家庄兄弟连教育 已关注:208 咨询电话:

相关知识点:提到,有些Android或者Java可能有所陌生,可能会提出种种问题,它是做什么的,是不是和线程有关,怎么使用呢?等等问题,本文将总结一下我对ThreadLocal的理解和认识,希望让大家理解ThreadLocal更加透彻一些。

ThreadLocal是一个关于创建线程局部变量的类。

通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。

上面的两个修饰看似矛盾,实则不然。

Global 意思是在当前线程中,任何一个点都可以访问到ThreadLocal的值。

Local 意思是该线程的ThreadLocal只能被该线程访问,一般情况下其他线程访问不到。

ThreadLocal mStringThreadLocal=new ThreadLocal<>();

mStringThreadLocal.set("droidyue.com");

mStringThreadLocal.get();

完整的使用示例

private void testThreadLocal() {

Thread t=new Thread() {

ThreadLocal mStringThreadLocal=new ThreadLocal<>();

@Override

public void run() {

super.run();

mStringThreadLocal.set("droidyue.com");

mStringThreadLocal.get();

}

};

t.start();

}

为ThreadLocal设置默认的get初始值,需要重写initialValue方法,下面是一段代码,我们将默认值修改成了线程的名字

ThreadLocal mThreadLocal=new ThreadLocal() {

@Override

protected String initialValue() {

return Thread.currentThread().getName();

}

};

在Android中,Looper类就是利用了ThreadLocal的特性,保证每个线程只存在一个Looper对象。

static final ThreadLocal sThreadLocal=new ThreadLocal();

private static void prepare(boolean quitAllowed) {

if (sThreadLocal.get() !=null) {

throw new RuntimeException("Only one Looper may be created per thread");

}

sThreadLocal.set(new Looper(quitAllowed));

}

为了更好的掌握ThreadLocal,我认为了解其内部实现是很有必要的,这里我们以set方法从起始看一看ThreadLocal的实现原理。

下面是ThreadLocal的set方法,大致意思为

首先获取当前线程

利用当前线程作为句柄获取一个ThreadLocalMap的对象

如果上述ThreadLocalMap对象不为空,则设置值,否则创建这个ThreadLocalMap对象并设置值

源码如下

public void set(T value) {

Thread t=Thread.currentThread();

ThreadLocalMap map=getMap(t);

if (map !=null)

map.set(this, value);

else

createMap(t, value);

}

下面是一个利用Thread对象作为句柄获取ThreadLocalMap对象的代码

ThreadLocalMap getMap(Thread t) {

return t.threadLocals;

}

上面的代码获取的实际上是Thread对象的threadLocals变量,可参考下面代码

class Thread implements Runnable {

ThreadLocal.ThreadLocalMap threadLocals=null;

}

而如果一开始设置,即ThreadLocalMap对象未创建,则新建ThreadLocalMap对象,并设置初始值。

void createMap(Thread t, T firstValue) {

t.threadLocals=new ThreadLocalMap(this, firstValue);

}

总结:实际上ThreadLocal的值是放入了当前线程的一个ThreadLocalMap实例中,所以只能在本线程中访问,其他线程无法访问。

在Java中,栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。

其实不是,因为ThreadLocal实例实际上也是被其创建的类持有(更顶端应该是被线程持有)。而ThreadLocal的值其实也是被线程实例持有。

它们都是位于堆上,只是通过一些技巧将可见性修改成了线程可见。

关于堆和栈的比较,请参考Java中的堆和栈的区别

既然上面提到了ThreadLocal只对当前线程可见,是不是说ThreadLocal的值只能被一个线程访问呢?

使用InheritableThreadLocal可以实现多个线程访问ThreadLocal的值。

如下,我们在主线程中创建一个InheritableThreadLocal的实例,然后在子线程中得到这个InheritableThreadLocal实例设置的值。

private void testInheritableThreadLocal() {

final ThreadLocal threadLocal=new InheritableThreadLocal();

threadLocal.set("droidyue.com");

Thread t=new Thread() {

@Override

public void run() {

super.run();

Log.i(LOGTAG, "testInheritableThreadLocal=" + threadLocal.get());

}

};

t.start();

}

上面的代码输出的日志信息为

I/MainActivity( 5046): testInheritableThreadLocal=droidyue.com

使用InheritableThreadLocal可以将某个线程的ThreadLocal值在其子线程创建时传递过去。因为在线程创建过程中,有相关的处理逻辑。

//Thread.java

private void init(ThreadGroup g, Runnable target, String name,

long stackSize, AccessControlContext acc) {

//code goes here

if (parent.inheritableThreadLocals !=null)

this.inheritableThreadLocals= ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

this.stackSize=stackSize;

tid=nextThreadID();

}

上面代码就是在线程创建的时候,复制父线程的inheritableThreadLocals的数据。

有网上讨论说ThreadLocal会导致内存泄露,原因如下

首先ThreadLocal实例被线程的ThreadLocalMap实例持有,也可以看成被线程持有。

如果应用使用了线程池,那么之前的线程实例处理完之后出于复用的目的依然存活

所以,ThreadLocal设定的值被持有,导致内存泄露。

上面的逻辑是清晰的,可是ThreadLocal并不会产生内存泄露,因为ThreadLocalMap做选择key的时候,并不是直接选择ThreadLocal实例,而是ThreadLocalMap实例的弱引用。

static class ThreadLocalMap {

static class Entry extends WeakReference> {

Object value;

Entry(ThreadLocal k, Object v) {

super(k);

value=v;

}

}

}

所以实际上从ThreadLocal设计角度来说是不会导致内存泄露的。关于弱引用,了解更多,请访问译文:理解Java中的弱引用

实现单个线程单例以及单个线程上下文信息存储,比如交易id等

实现线程安全,非线程安全的对象使用ThreadLocal之后就会变得线程安全,因为每个线程都会有一个对应的实例

  • 校区地址
  • 学校相册
  • 热门课程
  • 同类机构
  • 其他课程

温馨提示:提交留言后老师会第一时间与您联系!热线电话:

手机访问

#tel_400#