TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
因为我本身对thread�啥研究,这几天看了threadlocal特�去研究一下想跟大家讨论一下呵呵....
先介绍一下我在日本结城先生网站看的
http://www.hyuki.com/dp/dpinfo_ThreadSpecificStorage.HTML
Thread-Specific Storage pattern
它的code我转一下,如下
Thread-Specific Storage pattern
假设有一个如下的interface,当我呼叫完call()以后,想知道是否有发生error,或者发生什么error,那么就用errno()方法来调查.(这个前提听起来有一点笨,但是在实际的系统中却常存在)
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
(后略) |
|