use*_*525 7 java multithreading
我有一个int x应该同时从多个线程访问的字段.我希望x每个线程都有一个单独的副本,每个副本都以其原始值开始.我尝试使用volatile关键字执行此操作,但每个新线程仍会修改x其他线程.
这是一个代码示例:
public class StackOverflowThread0 {
public StackOverflowThread0() {
new A().start();
}
public static void main(String[] args) {
new StackOverflowThread0();
}
volatile int x = 0;//<--keep original for each thread?
class A extends Thread {
@Override
public void run() {
try {
while (true) {
getT().start();
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
Thread getT() {
Thread t = new Thread() {
@Override
public void run() {
x++;
for (int i = 0; i < 100; i++) {
try {
System.out.println("x=" + x + " | thread id=" + Thread.currentThread().getId() + "| 100*x+x=" + (100 * x + x));
Thread.sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
interrupt();
}
};
return t;
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101
x=1 | thread id=10| 100*x+x=101 //thread 10 has x field value as 1
x=2 | thread id=11| 100*x+x=202 //thread 11 modifies x field to 2
x=2 | thread id=10| 100*x+x=202 //thread 10 lost x value as 1 :(
etc...
Run Code Online (Sandbox Code Playgroud)
如何x为每个线程保留单独的值,或者是否有更优化的方法来解决任务?
ThreadLocal类可以帮助您实现这一点。它维护一个对于访问它的每个线程都不同的变量。换句话说,每个线程都有自己唯一的变量副本。
检查您的代码的以下更改:
//Initialisation of the variable. Here an initial value of zero is assigned.
ThreadLocal<Integer> x = ThreadLocal.withInitial(()-> 0);
//Incrementing the value by one:
x.set(x.get() + 1);
//Outputting the result:
System.out.println("x=" + x.get() + " | thread id="
+ Thread.currentThread().getId() + "| 100*x+x=" + (100 * x.get() + x.get()));
Run Code Online (Sandbox Code Playgroud)
编辑:对于那些使用 1.7 的人来说,确实有一种方法可以在不使用 lambda 表达式的情况下使用 ThreadLocal。不过,您必须重写initialValue() 方法。
ThreadLocal<Integer> x = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
844 次 |
| 最近记录: |