以下是该计划:
import java.util.Date;
public class ThreadLocalReplaceWithString {
public static class MyRunnable implements Runnable {
private String threadLocal = new String("");
@Override
public void run() {
threadLocal= new Date().toString();
try {
Thread.sleep(4000);
} catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName()+
" start time = "+threadLocal);
}
}
public static void main(String[] args) throws InterruptedException {
MyRunnable myRunnable = new MyRunnable();
Thread thread1 = new Thread(myRunnable,"Thread-1");
Thread thread2 = new Thread(myRunnable,"Thread-2");
thread1.start();
Thread.sleep(1000); //Start thread-2 after 1 second.
thread2.start();
}
}
输出:
Thread-1 start time = Fri May 19 06:45:47 IST 2017
Thread-2 start time = Fri May 19 06:45:47 IST 2017
为什么两个时间值都相同,即使每次开始新线程时都会实例化新日期。是因为多核处理器?
取自here
的计划答案 0 :(得分:3)
当您创建一个Runnable并将其引用传递给两个线程对象时,这意味着两个线程正在执行相同的Runnable,它们正在更改同一个对象。
run方法在设置实例变量并将其打印出来之间休眠4秒。第二个线程在一秒钟后启动。第二个线程有足够的时间用不同的字符串覆盖实例变量。当线程打印时,它们会在同一个Runnable上打印相同的值。
您链接到的文章的作者所指出的是,即使两个线程使用相同的Runnable实例,当更改的值在ThreadLocal中时,每个线程也会单独保存自己的值。发布的代码显示了使用共享Runnable的普通实例成员的相反情况,以便相反地显示ThreadLocal有用的原因。
如果您不希望线程共享状态,请为每个线程分配自己的Runnable,或使用ThreadLocal。 Threadlocal在交叉情况下非常有用,可以将对象限制在线程中,您希望线程执行不同的方法来访问同一个对象而不显式传递它。 (有一种常见的场景使用threadlocal来存储非线程安全类SimpleDateFormat的实例。)
不要反复进行同步,很多时候最直接的答案是避免共享。
答案 1 :(得分:0)
此 预期输出。 The page you took the code from说:
ThreadLocal替换为String。 Thread-1的threadLocal值被Thread-2的threadLocal值覆盖。因此,threadLocal为两个线程打印了相同的开始时间。