Java多线程大总结 这个代码就是说明如何使用手动加锁的方式进行线程资源同步,并获得更高的性能。 3.ThreadLocal 早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。 ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。 在 同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写, 什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。而ThreadLocal则从另一个角度来解决多线程的并发访 问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就 没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。 由 于ThreadLocal中可以持有任何类型的对象,低版本JDK所提供的get()返回的是Object对象,需要强制类型转换。但JDK 5.0通过泛型很好的解决了这个问题,在一定程度地简化ThreadLocal的使用,概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换 空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变 量,因此可以同时访问而互不影响。 ThreadLocal类接口很简单,只有4个方法,我们先来了解一下: void set(Object value) 设置当前线程的线程局部变量的值。 public Object get() 该方法返回当前线程所对应的线程局部变量。 public void remove() 将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。 protected Object initialValue() 返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。 值 得一提的是,在JDK5.0中,ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal<T>。API方法也相应进 行了调整,新版本的API方法分别是void set(T value)、T get()以及T initialValue()。 有关于ThreadLocal的内容非常之多,很多数据库连接池就是基于ThreadLocal的,例如OSChina的数据库链接池就是使用ThreadLocal自己封装的。关于ThreadLocal的内容大家可以自己再搜索学习一下。
123456789101112131415161718192021222324252627282930313233
class
Data {???
????
private
int
data;
// 共享数据
????
private
ReadWriteLock rwl =
new
ReentrantReadWriteLock();??
????
public
void
set(
int
data) {
????????
rwl.writeLock().lock();
// 取到写锁
????????
try
{
????????????
System.out.println(Thread.currentThread().getName() +
"准备写入数据"
);
????????????
try
{
????????????????
Thread.sleep(
20
);
????????????
}
catch
(InterruptedException e) {
????????????????
e.printStackTrace();
????????????
}
????????????
this
.data = data;
????????????
System.out.println(Thread.currentThread().getName() +
"写入"
+
this
.data);
????????
}
finally
{
????????????
rwl.writeLock().unlock();
// 释放写锁
????????
}
????
}??
????
public
void
get() {
????????
rwl.readLock().lock();
// 取到读锁
????????
try
{
????????????
System.out.println(Thread.currentThread().getName() +
"准备读取数据"
);
????????????
try
{
????????????????
Thread.sleep(
20
);
????????????
}
catch
(InterruptedException e) {
????????????????
e.printStackTrace();
????????????
}
????????????
System.out.println(Thread.currentThread().getName() +
"读取"
+
this
.data);
????????
}
finally
{
????????????
rwl.readLock().unlock();
// 释放读锁
????????
}
????
}
}