ThreadLocal类的理解与使用
在java线程中有一个很有作用的类ThreadLocal
?
在网上关于ThreadLocal的理解也相当的多,文章也很多,但是很多看了都让人一头雾水,有的就讲原理,有的就说概念,而且大量的转载,却很少有实例这块的。
?
JDK1.5之后,java引入了泛型的概念,也为ThreadLocal引入了泛型,通过泛型可以简化多线程编程时的并发访问,使用这个工具类可以很简洁的编写出有没的多线程程序。
?
ThreadLocal 是Thread Local Variable(线程局部变量)的意思,线程局部变量的功能非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,使每一个想成都可以独立的改变自己的副本,而不会和其他线程的副本冲突,从线程的角度看,就好像每一个线程都完全拥有该变量
ThreadLocal 类的用法很简单,它只提供了三个方法。
T get();返回此线程局部变量中当前线程副本中的值。
void remove();删除此线程局部变量中当前线程副本中的值。
void set(T value);设置此线程局部变量中当前线程副本中的值。
?
下面将通过两个程序的对比来说明ThreadLocal类的作用。
下面提供两个账户类
package test7;public class Account {/** * 定义一个ThreadLocal类变量 * 该变量将是一个线程局部变量,每个线程都会保留该变量的一个副本 */private ThreadLocal<String> name = new ThreadLocal<String>();public String getName() {return this.name.get();}public void setName(String name) {this.name.set(name);}}package test7;public class Account1 {/** * 定义一个ThreadLocal类变量 * 该变量将是一个线程局部变量,每个线程都会保留该变量的一个副本 */private String name ;public String getName() {return this.name;}public void setName(String name) {this.name = name;}}
?
以上的账户类中只有name这一个属性,不同的是前者使用了ThreadLocal来存贮,后者就是一个String
?
下面是线程类
package test7;public class Thread2 extends Thread{private Account1 account;public Thread2(Account1 account,String name){super(name);this.account = account;}@Overridepublic void run(){for (int i = 0; i < 10; i++) {//当i为6的时候将当前账户名换成当前线程名if(i == 6){this.account.setName(getName());}System.out.println(account.getName()+"账户的i的值为"+i);}}}
?这个类,是对每个账户进行操作,当运行到6的时候就将账户名改为当前线程的名字(getName()是Thread类中定义的方法)。
场景类是这样的
package test7;public class Test7 {public static void main(String[] args) {Account1 account = new Account1();Thread thread1 = new Thread2(account,"xby");Thread thread2 = new Thread2(account,"gengu");thread1.start();thread2.start();}}
?
如果使用Account1的话会出现什么结果?
null账户的i的值为0null账户的i的值为1null账户的i的值为2null账户的i的值为3null账户的i的值为4null账户的i的值为5xby账户的i的值为6xby账户的i的值为7xby账户的i的值为8xby账户的i的值为9xby账户的i的值为0xby账户的i的值为1xby账户的i的值为2xby账户的i的值为3xby账户的i的值为4xby账户的i的值为5gengu账户的i的值为6gengu账户的i的值为7gengu账户的i的值为8gengu账户的i的值为9
?如果使用Account类那么会出现什么结果?
null账户的i的值为0null账户的i的值为1null账户的i的值为2null账户的i的值为3null账户的i的值为4null账户的i的值为5xby账户的i的值为6xby账户的i的值为7xby账户的i的值为8xby账户的i的值为9null账户的i的值为0null账户的i的值为1null账户的i的值为2null账户的i的值为3null账户的i的值为4null账户的i的值为5gengu账户的i的值为6gengu账户的i的值为7gengu账户的i的值为8gengu账户的i的值为9
?不知道你们看出差别没有,就是后者相对非常独立,第一次accout变量的name属性改变之后没有使第二个线程中的account name变量改变。还是null,这回应该有点了解了吧。第一次运行的时候,线程1改变了线程2中account变量的name属性。
?
这样就好像,两个线程各拥有一个account实例一样。
?
但是ThreadLocal不能替代同步机制,因为他不能解决同步问题,只能解决共享安全问题,从根本上避免了多个线程之间的资源共享,所以也就不需要同步了。
?
?