首页
论坛
图书
开发资料
在线文档
网址
下载
联系我们
 新闻│Java│JavaScript│Eclipse│Eclipse 英文│J2EE│J2ME│J2SE│JSP│Netbeans│Hibernate│JBuilder│Spring│Struts
站内搜索: 请输入搜索关键词

当前页面: 开发资料首页 → Java 专题 → ThreadLocal的用法

ThreadLocal的用法

摘要: ThreadLocal的用法

</td> </tr> <tr> <td height="35" valign="top" class="ArticleTeitle"> <table width="679" border="0"> <tr> <td width="395"> 因为我本身对thread沒啥研究,这几天看了threadlocal特別去研究一下想跟大家讨论一下呵呵....

先介绍一下我在日本结城先生网站看的
http://www.hyuki.com/dp/dpinfo_ThreadSpecificStorage.html
Thread-Specific Storage pattern

它的code我转一下,如下

Thread-Specific Storage pattern
假设有一个如下的interface,当我呼叫完call()以后,想知道是否有发生error,或者发生什么error,那么就用errno()方法来调查.(这个前提听起来有一点笨,但是在实际的系统中却常存在)

</td> <td width="274" align="center"> </td> </tr> </table>

LegacySystem.java

interface LegacySystem {
public void call(int parameter);
public int errno();
}


在这边我们实现了上面的interface,
为了简单一点,在这里不做任何复杂动作,只单纯把parameter传给errno

class LegacySystemImpl implements LegacySystem {
private int errno;
public void call(int parameter) {
errno = parameter;
}

public int errno() { return errno; }
}

上面的code很简单只是传入参数,还有印出的动作。

如果在single thread下,上面的class不会有任何问题,但是当LegacySystemImpl物件被复数的thread存取,那么将会发生问题,也就是说其他的thread呼叫call会影响到自己呼叫errno()方法的结果。

主要的如下
现在两个thread去呼叫,第一个thread一直去呼叫call(0),然后5秒以后第二个thread一直呼叫call(1),如果发生传入call的值和errno()方法回转的值不同时,印出???并呼叫System.exit结束。

Main1.java
class Main1 extends Thread {
private static LegacySystem system = new LegacySystemImpl();
private int value = 0;
public Main1(int value) {
this.value = value;
}

public void run() {
while (true) {
System.out.println(Thread.currentThread().getName()+ " checks.");
system.call(value);
try {
Thread.sleep(100);
}catch (InterruptedException e) {}
int errno = system.errno();
System.out.println(Thread.currentThread().getName()+ ": value = " + value + ", errno = " + errno);
if (value != errno) {
System.out.println("???");
System.exit(0);
}
}
}

public static void main(String[] args) {
new Main1(0).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {}
new Main1(1).start();
}
}


结果如下
Thread-0 checks.
Thread-0: value = 0, errno = 0
Thread-0 checks.
Thread-0: value = 0, errno = 0
Thread-0 checks.
Thread-0: value = 0, errno = 0
(中略)
Thread-0 checks.
Thread-0: value = 0, errno = 0
Thread-0 checks.
Thread-1 checks. ←Thread-1启动以后…
Thread-0: value = 0, errno = 1 ←结果乱七八糟。
???

所以现在改写成如下的proxy

LegacySystemProxy.java

class LegacySystemProxy implements LegacySystem {
private ThreadLocal thlocal = new ThreadLocal();
public void call(int parameter) {
getImpl().call(parameter);
}

public int errno() {
return getImpl().errno();
}

private LegacySystemImpl getImpl() {
LegacySystemImpl impl = (LegacySystemImpl)thlocal.get();
if (impl == null) {
impl = new LegacySystemImpl();
thlocal.set(impl);
}
return impl;
}
}

在这里使用的java.lang.ThreadLocal,让现在的thread保有其固有的领域(对thread来说specific的领域),为了让thread有固有的LegacySystemImpl,所以使用threadlocal,使用threadlocal的get和set方法可以去读现在的thread的固有领域

写个新的main

Main2.java

class Main2 extends Thread {
private static LegacySystem system = new LegacySystemProxy();
private int value = 0;
public Main2(int value) {
this.value = value;
}

public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " checks.");
system.call(value);
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
int errno = system.errno();
System.out.println(Thread.currentThread().getName() + ": value = " + value + ", errno = " + errno);
if (value != errno) {
System.out.println("???");
System.exit(0);
}
}
}

public static void main(String[] args) {
new Main2(0).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {}
new Main2(1).start();
}
}


结果如下

Thread-0 checks.
Thread-0: value = 0, errno = 0
(中略)
Thread-0 checks.
Thread-1 checks.
Thread-0: value = 0, errno = 0
Thread-0 checks.
Thread-1: value = 1, errno = 1
Thread-1 checks.
Thread-0: value = 0, errno = 0
Thread-0 checks. ←就像这样
Thread-1 checks. ←就算这样也不怕。
Thread-0: value = 0, errno = 0
Thread-0 checks.
Thread-1: value = 1, errno = 1
Thread-1 checks.
Thread-0: value = 0, errno = 0
(后略)

function TempSave(ElementID) { CommentsPersistDiv.setAttribute("CommentContent",document.getElementById(ElementID).value); CommentsPersistDiv.save("CommentXMLStore"); } function Restore(ElementID) { CommentsPersistDiv.load("CommentXMLStore"); document.getElementById(ElementID).value=CommentsPersistDiv.getAttribute("CommentContent"); } </td> </tr> <tr>


↑返回目录
前一篇: JAVA中的指针,引用及对象的clone
后一篇: Java解析网络数据流的三种特殊方法

首页 | 全站 Sitemap | 联系我们 | 设为首页 | 收藏本站
版权所有 Copyright © 2006-2007, Java 编程资料牛鼻站, All rights reserved