//以下代码存在问题
public class ThreadLocalDemo {
//private static ThreadLocal<String> tl = new ThreadLocal<String>(); //①
private String name; //线程不安全的变量
public String getName() {
return name;
//return tl.get(); //②
}
public void setName(String name) {
this.name = name;
//tl.set(name); //③
}
public static void main(String[] args) {
ThreadLocalDemo demo = new ThreadLocalDemo(); //一个SingleTon实例
//模拟并发访问(第二个参数表示用户访问时输入的用户名)
VisitThread visitor1 = new VisitThread(demo, "Bruce"); //访问者1
VisitThread visitor2 = new VisitThread(demo, "Phil"); //访问者2
VisitThread visitor3 = new VisitThread(demo, "David"); //访问者3
visitor1.start();
visitor2.start();
visitor3.start();
}
/**
* 访问线程(一个线程代表一个并发时的不同用户访问)
*/
private static class VisitThread extends Thread {
private ThreadLocalDemo demo;
private String name;
public VisitThread(ThreadLocalDemo demo, String name) {
this.demo = demo;
this.name = name;
}
public void run() {
demo.setName(name);
String tempName = name; //tempName是线程安全的
//让程序暂停一秒,以便显示线程不安全而出现的错误
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread[" + this.currentThread().getName() + "] name[" + demo.getName() + "]" + " (should be[" + tempName + "])");
}
}
}
运行输出如下
Thread[Thread-0] name[David] (should be[Bruce])
Thread[Thread-2] name[David] (should be[David])
Thread[Thread-1] name[David] (should be[Phil])
问题:可以看到三个用户输入的名字都变成了"David"(demo.getName() = "David")
要解决以上问题,可以选择用synchronized同步,这样就影响了并发性能。
我们也可以选择一种不影响并发性能的解决方案。把①的注释放开,getName() 和setName()换成②和③,这样好能解决并发问题。
再次运行输出如下
Thread[Thread-2] name[David] (should be[David])
Thread[Thread-1] name[Phil] (should be[Phil])
Thread[Thread-0] name[Bruce] (should be[Bruce])
以上主要是举个并发问题的例子,如果想更了解ThreadLocal,可以看下面的文章
http://www.builder.com.cn/2007/0529/404695.shtml
分享到:
相关推荐
目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现...注意事项使用ThreadLocal解决SimpleDateFormat线程安全问题总结...
Java中的ThreadLocal是解决线程安全问题的一个重要工具,它提供了一种在多线程环境下为每个线程维护独立变量副本的方法,从而避免了共享状态带来的竞态条件和线程安全问题。 线程安全问题通常由全局变量和静态变量...
解决Servlet的线程安全问题通常有以下几种策略: 1. **避免使用实例变量**:尽可能使用局部变量,局部变量只存在于方法的执行上下文中,不会被多个线程共享,因此不存在线程安全问题。 2. **使用同步控制**:通过`...
SimpleDateFormat类的线程安全问题和解决方案 SimpleDateFormat类的线程安全问题 SimpleDateFormat类是Java提供的日期时间转化类,用于将日期和时间类型的数据进行解析和格式化。在Java开发中,SimpleDateFormat类...
在Java中,解决线程安全问题有多种方式: 1. **同步机制**:包括`synchronized`关键字和`java.util.concurrent`包中的工具类。`synchronized`可以保证在同一时刻,只有一个线程能执行特定代码块,防止数据不一致。...
- 由于每次请求都会创建新的`Action`实例,因此`Action`类中的成员变量对于每个请求来说都是独立的,从而自动解决了线程安全问题。 - 这种做法降低了开发人员需要关注线程安全问题的复杂度,提高了开发效率。 ###...
在C#中,实现线程安全通常有几种策略:锁(Lock)、Monitor、Mutex、Semaphore以及线程局部存储(ThreadLocal)等。 这个压缩包中的"TestConsoleApp"很可能是一个演示程序,展示了如何使用封装好的线程安全日志类。在...
- 使用ThreadLocal解决线程安全问题的场景。 4. **Java内存模型** - 描述堆内存和栈内存的区别。 - 讲解Java内存区域,包括堆、栈、方法区、程序计数器等。 - 分析JVM内存溢出(OOM)问题的常见原因及解决办法...
8. 线程局部变量(ThreadLocal):为每个线程创建独立的变量副本,避免了线程安全问题,但要注意,ThreadLocal变量会在线程结束时被垃圾回收,如果不及时清理可能导致内存泄漏。 测试线程安全通常包括模拟并发环境...
3. 线程安全:ThreadLocal可以解决多线程编程中的线程安全问题,但是需要正确地使用ThreadLocal来避免线程安全问题。 ThreadLocal是一种非常有用的机制,可以解决多线程编程中的线程安全问题,但是需要正确地使用...
- ThreadLocal不是线程同步机制,不能用来解决多个线程访问共享资源的问题。 - 不要将ThreadLocal用作全局变量,否则可能导致内存泄漏。 - 使用ThreadLocal时,要特别注意线程结束后的清理工作,防止内存泄漏。 - ...
ThreadLocal通常被用来解决线程共享数据时可能出现的并发问题,避免了使用synchronized关键字进行同步控制的复杂性。 在Java中,ThreadLocal的工作原理是为每个线程创建一个单独的存储空间,每个线程可以独立地读写...
解决线程安全问题的方法 1. **使用同步机制**:可以使用`synchronized`关键字或者`java.util.concurrent`包中的工具类来控制对实例变量的访问,确保在同一时间只有一个线程能修改这些变量。 2. **避免使用实例变量*...
ThreadLocal变量是另一种保证线程安全的方法,它为每个线程提供了一个变量的副本,使得每个线程都可以独立地修改自己的副本,而不会影响其他线程。ThreadLocal适用于那种线程间不需要共享数据,或者共享的数据需要以...
2. 使用ThreadLocal解决线程安全问题 为了解决SimpleDateFormat类的线程安全问题,可以使用ThreadLocal类。ThreadLocal类可以使线程绑定到指定的对象,从而避免了线程之间的对象共享问题。在示例代码中,我们使用...
在Java编程中,ThreadLocal是线程局部变量的类,它为每个线程提供了一个独立的变量副本,...总的来说,ThreadLocal是Java中解决线程间数据隔离问题的强大工具,但在使用时需要注意内存管理和线程安全,避免潜在的问题。