Java ThreadLocal使用浅析
2009-08-18 20:14
429 查看
Java ThreadLocal使用浅析
JAVA API
文档里关于
ThreadLocal
的定义是:
This
class provides thread-local variables. These variables differ from
their normal counterparts in that each thread that accesses one (via
its
get
or
set
method) has its own, independently initialized copy of the variable.
ThreadLocal
instances are typically private static fields in classes that wish to
associate state with a thread (e.g., a user ID or Transaction ID).
这个类提供了一个线程本地的变量。这些变量在被共享访问的情况下在不同的线程里是独立的
(
必须通过
get
和
set
方法来访问
)
。
很显然该类提供了一个机制可以防止多线程访问带来的不安全机制。实际上就是在线程本地保存一个变量,而不是通过共享变量。这个就要看我们的使用场合了,如果我们确实需要共享的数据,那还是必须通过同步机制来保证数据的安全。如果有些情况希望不同的线程保存的变量各自分开,那用这个还是比较合适的。
ThreadLocal
这个类本身不是代表线程要访问的变量,这个类的成员变量才是。
JDK1.5
给
ThreadLocal
加了泛型功能,即是
ThreadLocal<T>,
这个泛型
T
即是要线程的本地变量。线程通过
ThreadLocal
的
get
和
set
方法去访问这个变量
T
。
ThreadLocal
提供了一个机制,它能保证线程通过这个来访问它来访问类型为
T
的变量的时候是不同的拷贝。所以访问该变量必须通过
Threadlocal
这个类只提供了两个
public
方法,即是
get()
和
set
()方法来访问。
同时还提供了一个
inintValue()
的
protected
方法。该方法用来初始化变量值。
注意
:默认情况下
initValue(),
返回
null
。线程在没有调用
set
之前,第一次调用
get
的时候,
get
方法会默认去调用
initValue
这个方法。所以如果没有覆写这个方法,可能导致
get
返回的是
null
。当然如果调用过
set
就不会有这种情况了。但是往往在多线程情况下我们不能保证每个线程的在调用
get
之前都调用了
set
,所以最好对
initValue
进行覆写,以免导致空指针异常。
说了这么多,估计还不如看下例子吧,下面还是上例子。
例子
1
:没有使用
Threadlocal
的情况:
/**
*
*
@author
yblin
*
2009.8.18
*
*/
public
class
TestWithNoThreadLocal
{
public
static
int
a
=
0;
public
static
void
main(String[]
args)
{
MyThread
myThread
=
new
MyThread();
myThread.start();
for
(
int
i
=
0;
i
<
5;
i++)
{
a
=
a
+
1;
System.
out
.println(Thread.
currentThread
().getName()
+
":"
+
a
);
}
}
public
static
class
MyThread
extends
Thread
{
public
void
run()
{
for
(
int
i
=
0;
i
<
5;
i++)
{
a
=
a
+
1;
System.
out
.println(Thread.
currentThread
().getName()
+
":"
+
a
);
}
}
}
}
运行的一种结果如下:
main:2
Thread-0:2
main:3
Thread-0:4
main:5
Thread-0:6
main:7
Thread-0:8
main:9
Thread-0:10
在没有同步的机制下,该结果有不安全的情况发生是正常的,两个线程都得到
2
。下面请看用了
ThreadLocal
的效果。
例子
2
:使用了
Threadlocal
的情况:
/**
*
*
@author
yblin
*
2009.8.18
*
*/
public
class
TestThreadLocal2
{
private
static
ThreadLocal<Integer>
a
=
new
ThreadLocal<Integer>()
{
public
Integer
initialValue()
{
//
初始化,默认是返回
null
return
0;
}
};
public
static
void
main(String
args[])
{
MyThread
my;
my
=
new
MyThread();
my.start();
for
(
int
i
=
0;
i
<
5;
i++)
{
a
.set(
a
.get()
+
1);
System.
out
.println(Thread.
currentThread
().getName()
+
":"
+
a
.get());
}
}
public
static
class
MyThread
extends
Thread
{
public
void
run()
{
for
(
int
i
=
0;
i
<
5;
i++)
{
a
.set(
a
.get()
+
1);
System.
out
.println(Thread.
currentThread
().getName()
+
":"
+
a
.get());
}
}
}
}
运行的一种结果如下:
main:1
Thread-0:1
main:2
Thread-0:2
main:3
Thread-0:3
main:4
Thread-0:4
Thread-0:5
main:5
如上是关于
ThreadLocal
的简单介绍。其内部具体实现可看其类实现。
JAVA API
文档里关于
ThreadLocal
的定义是:
This
class provides thread-local variables. These variables differ from
their normal counterparts in that each thread that accesses one (via
its
get
or
set
method) has its own, independently initialized copy of the variable.
ThreadLocal
instances are typically private static fields in classes that wish to
associate state with a thread (e.g., a user ID or Transaction ID).
这个类提供了一个线程本地的变量。这些变量在被共享访问的情况下在不同的线程里是独立的
(
必须通过
get
和
set
方法来访问
)
。
很显然该类提供了一个机制可以防止多线程访问带来的不安全机制。实际上就是在线程本地保存一个变量,而不是通过共享变量。这个就要看我们的使用场合了,如果我们确实需要共享的数据,那还是必须通过同步机制来保证数据的安全。如果有些情况希望不同的线程保存的变量各自分开,那用这个还是比较合适的。
ThreadLocal
这个类本身不是代表线程要访问的变量,这个类的成员变量才是。
JDK1.5
给
ThreadLocal
加了泛型功能,即是
ThreadLocal<T>,
这个泛型
T
即是要线程的本地变量。线程通过
ThreadLocal
的
get
和
set
方法去访问这个变量
T
。
ThreadLocal
提供了一个机制,它能保证线程通过这个来访问它来访问类型为
T
的变量的时候是不同的拷贝。所以访问该变量必须通过
Threadlocal
这个类只提供了两个
public
方法,即是
get()
和
set
()方法来访问。
同时还提供了一个
inintValue()
的
protected
方法。该方法用来初始化变量值。
注意
:默认情况下
initValue(),
返回
null
。线程在没有调用
set
之前,第一次调用
get
的时候,
get
方法会默认去调用
initValue
这个方法。所以如果没有覆写这个方法,可能导致
get
返回的是
null
。当然如果调用过
set
就不会有这种情况了。但是往往在多线程情况下我们不能保证每个线程的在调用
get
之前都调用了
set
,所以最好对
initValue
进行覆写,以免导致空指针异常。
说了这么多,估计还不如看下例子吧,下面还是上例子。
例子
1
:没有使用
Threadlocal
的情况:
/**
*
*
@author
yblin
*
2009.8.18
*
*/
public
class
TestWithNoThreadLocal
{
public
static
int
a
=
0;
public
static
void
main(String[]
args)
{
MyThread
myThread
=
new
MyThread();
myThread.start();
for
(
int
i
=
0;
i
<
5;
i++)
{
a
=
a
+
1;
System.
out
.println(Thread.
currentThread
().getName()
+
":"
+
a
);
}
}
public
static
class
MyThread
extends
Thread
{
public
void
run()
{
for
(
int
i
=
0;
i
<
5;
i++)
{
a
=
a
+
1;
System.
out
.println(Thread.
currentThread
().getName()
+
":"
+
a
);
}
}
}
}
运行的一种结果如下:
main:2
Thread-0:2
main:3
Thread-0:4
main:5
Thread-0:6
main:7
Thread-0:8
main:9
Thread-0:10
在没有同步的机制下,该结果有不安全的情况发生是正常的,两个线程都得到
2
。下面请看用了
ThreadLocal
的效果。
例子
2
:使用了
Threadlocal
的情况:
/**
*
*
@author
yblin
*
2009.8.18
*
*/
public
class
TestThreadLocal2
{
private
static
ThreadLocal<Integer>
a
=
new
ThreadLocal<Integer>()
{
public
Integer
initialValue()
{
//
初始化,默认是返回
null
return
0;
}
};
public
static
void
main(String
args[])
{
MyThread
my;
my
=
new
MyThread();
my.start();
for
(
int
i
=
0;
i
<
5;
i++)
{
a
.set(
a
.get()
+
1);
System.
out
.println(Thread.
currentThread
().getName()
+
":"
+
a
.get());
}
}
public
static
class
MyThread
extends
Thread
{
public
void
run()
{
for
(
int
i
=
0;
i
<
5;
i++)
{
a
.set(
a
.get()
+
1);
System.
out
.println(Thread.
currentThread
().getName()
+
":"
+
a
.get());
}
}
}
}
运行的一种结果如下:
main:1
Thread-0:1
main:2
Thread-0:2
main:3
Thread-0:3
main:4
Thread-0:4
Thread-0:5
main:5
如上是关于
ThreadLocal
的简单介绍。其内部具体实现可看其类实现。
相关文章推荐
- Java ThreadLocal使用浅析
- Java ThreadLocal使用浅析
- Java ThreadLocal的使用
- 浅析 Java ThreadLocal
- JAVA Threadlocal 的使用
- java ThreadLocal设计与使用
- Java ThreadLocal的使用
- java ThreadLocal 使用详解
- Java ThreadLocal使用
- JAVA ThreadLocal对象浅析
- java.lang.ThreadLocal的简单使用
- [置顶] Java 多线程学习笔记(十) InheritableThreadLocal的使用
- java学习——ThreadLocal 线程局部 (thread-local) 变量的使用
- Java ThreadLocal的使用
- JAVA ThreadLocal对象浅析
- Java使用ThreadFactory来创建新的线程
- 浅析Java中Runnable和Thread的区别
- Java并发编程:Thread类的使用
- mybatis中使用Java8的日期LocalDate、LocalDateTime
- 浅析 Java Thread.join()