读书人

线程保险和ThreadLocal入门

发布时间: 2012-09-05 15:19:34 作者: rapoo

线程安全和ThreadLocal入门

原帖地址:http://javapapers.com/core-java/threadlocal/

尝试翻译,欢迎批评指正。

原文地址:http://javapapers.com/core-java/threadlocal/

ThreadLocal的核心概念是没一个线程可以通过get或者set方法访问它自己的、独立初始化的变量的副本。

1. ThreadLocal介绍

为了在多线程环境下不出现任何的冲突,我们希望能否分离一个类的多个实例。对于每一个线程来说,没一个实例都是唯一的。这不过是实现线程安全的一个方式。

线程安全的另外的重要的一点是能够全局访问。可以在线程内部的任何地方进行访问。记住:应该声明成static和final的。

2. 什么是线程安全

线程是进程的一条单独的线。当我们提到多线程应用的时候,我们的意思是一个进程的多个线程访问同一行代码。在这个情况下,存在一个线程访问或者修改另一个线程的数据的可能性。当数据不允许这样共享的时候,我们应该做成线程安全的。实现线程安全的方式有下面几种:

重入

互斥(同步机制)

ThreadLocal

原子操作

3. 使用ThreadLocal

(引用Joshua Bloch的一段话,巨抽象,我没看懂,......)

我们有一个非线程安全的变量,我们想把它变成线程安全的,可以考虑同步机制把对象封闭到同步块中。另外的方式是使用ThreadLocal,为每一个线程持有单独的对象使得变得安全。

4. ThreadLocal的例子

package com.javapapers;

import java.text.SimpleDateFormat;

import java.util.Date;

public class ThreadLocalExample {

private static final ThreadLocal formatter = new ThreadLocal() {

protected SimpleDateFormat initialValue() {

return new SimpleDateFormat("yyyyMMdd HHmm");

}

};

public String formatIt(Date date) {

return formatter.get().format(date);

}

}

上边的代码中,关键要理解get()方法。他返回的当前线程的ThreadLocal变量的副本。如果当前线程的这个变量还没有值,则通过调用initalValue方法返回第一次初始化的值。

JavaDoc中的例子

下面的例子为每一个线程生成一个唯一的标识符。第一次调用get方法的时候指定一个线程的id,并且在随后的调用中保持不变。

port java.util.concurrent.atomic.AtomicInteger;

public class ThreadId {

// Atomic integer containing the next thread ID to be assigned

private static final AtomicInteger nextId = new AtomicInteger(0);

// Thread local variable containing each thread's ID

private static final ThreadLocal threadId =

new ThreadLocal() {

@Override protected Integer initialValue() {

return nextId.getAndIncrement();

}

};

// Returns the current thread's unique ID, assigning it if necessary

public static int get() {

return threadId.get();

}

}

5. Java API中ThreadLocal 的使用

在JDK1.7中,我们有一个叫做ThreadLocalRandom的新类。它用于为并行的线程生成随机数,每一个线程是随机数的种子都是唯一的。这是一个非常酷的功能。

下面的代码是上边的类实现ThreadLocal 的代码:

private static final ThreadLocal localRandom =

new ThreadLocal() {

protected ThreadLocalRandom initialValue() {

return new ThreadLocalRandom();

}

};

使用ThreadLocalRandom

package com.javapapers;

import java.util.concurrent.ThreadLocalRandom;

public class ThreadLocalRandomExample {

public static void main(String args[]) throws InterruptedException {

//tossing 3 coins

for (int i = 0; i < 3; i++) {

final Thread thread = new Thread() {

public void run() {

System.out.print(Thread.currentThread().getName() + ":");

// generating 3 random numbers - random for every thread

for (int j = 0; j < 3; j++) {

final int random = ThreadLocalRandom.current().nextInt(

1, 3);

System.out.print(random + ",");

}

System.out.println();

}

};

thread.start();

thread.join();

}

}

}

6. ThreadLocal和内存泄露

ThreadLocal不是一个魔鬼,而是一个优秀的、实用的API。完全取决于我们怎么样去使用。我们应该学会在正确的场合使用合适的工具。我们不能使用大炮打蚊子,但是也不能谴责大炮。

PDF文件下载:

http://download.csdn.net/detail/licl19870605/4529958

读书人网 >编程

热点推荐