在java中,如果某个对象是非线程安全的共享资源,在多线程环境下,如果不加任何限制,对该资源的访问会存在冲突问题(比如多线程访问打印对象的属性序列号 如下面代码:)。针对这个问题,有以下几种解决方案:
1.加synchronized关键字,这种做法会限制并发访问,影响效率;
2.使用ThreadLocal维护共享资源(变量),为每个使用共享资源(变量)的线程提供独立的变量副本,从而避免冲突问题
- package test.threadlocal;
- /*
- * 序列号产生类
- */
- public class SequenceNumber
- {
- //序列号变量
- private int segNum=0;
- //获取下一个序列值
- public int getNextNum(){
- return ++segNum;
- }
- }
- package test.threadlocal;
- public class ThreadPrint extends Thread{
- //序列号产生类对象
- private SequenceNumber sn;
- //构造函数
- public ThreadPrint(String name,SequenceNumber sn) {
- super(name);
- this.sn = sn;
- }
- public void run() {
- for (int i = 0; i < 3; i++) {
- //每个线程打出3个序列值
- System.out.println(getName()+":sn--->" + sn.getNextNum());
- }
- }
- }
- package test.threadlocal;
- public class TestThreadLocal
- {
- public static void main(String[] args)
- {
- SequenceNumber sn = new SequenceNumber();
- // 3个线程共享sn,各自产生序列号
- ThreadPrint t1 = new ThreadPrint("A",sn);
- ThreadPrint t2 = new ThreadPrint("B",sn);
- ThreadPrint t3 = new ThreadPrint("C",sn);
- t1.start();
- t2.start();
- t3.start();
- }
- }
- A:sn--->1
- C:sn--->3
- B:sn--->2
- C:sn--->5
- C:sn--->7
- A:sn--->4
- A:sn--->8
- B:sn--->6
- B:sn--->9
把共享的序列号变量,用ThreadLocal变量来指定
- package test.threadlocal;
- /*
- * 序列号产生类
- */
- public class SequenceNumber
- {
- //序列号变量,通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值
- private static ThreadLocal seqNum = new ThreadLocal() {
- public Integer initialValue() {
- return 0;
- }
- };
- //获取下一个序列值
- public int getNextNum() {
- seqNum.set(seqNum.get() + 1);
- return seqNum.get();
- }
- }
输出:
B:sn--->1
C:sn--->1
A:sn--->1
C:sn--->2
B:sn--->2
C:sn--->3
A:sn--->2
A:sn--->3
B:sn--->3
阅读(778) | 评论(0) | 转发(0) |