package com.itheima.hello.runnable;
import java.util.Random;
public class ThreadDemo1 implements Runnable {
private int count = 0;
Student student = new Student();
private Object studentLock = new Object();
private Object countLock = new Object();
public static void main(String[] agrs) {
ThreadDemo1 td = new ThreadDemo1();
Thread t1 = new Thread(td, "a");
Thread t2 = new Thread(td, "b");
t1.start();
t2.start();
}
/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public void run() {
accessStudent();
}
public void accessStudent() {
long startTime = System.currentTimeMillis();
String currentThreadName = Thread.currentThread().getName();
System.out.println(currentThreadName + " is running!");
// System.out.println("first read age is:"+this.student.getAge());
/* 同步代码块 */
synchronized (countLock) {
try {
this.count++;
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("thread " + currentThreadName + " read count:"
+ this.count);
}
synchronized (studentLock) {
Random random = new Random();
int age = random.nextInt(100);
System.out.println("thread " + currentThreadName + " set age to:"
+ age);
synchronized (this) {
this.student.setAge(age);
System.out.println("thread " + currentThreadName
+ " first read age is:" + this.student.getAge());
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("thread " + currentThreadName+" second read age is:" + this.student.getAge());
}
long endTime = System.currentTimeMillis();
long spendTime = endTime - startTime;
System.out.println(Thread.currentThread().getName()+"花费时间:" + spendTime + "毫秒");
}
public class Student {
private int age = 0;
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
}
/*
* 首次读取和second读取不同,这样是错误的,那么我们需要实现synchornized synchronized 的同步代码块
* 使用同步代码块的话,需要对方法进行同步的代价是非常昂贵的
* 。特别是当被同步的方法执行一个冗长的操作。这个方法执行会花费很长的时间,对这样的方法进行同步可能会使系统性能成数量级的下降。 我们可以将同步细化一下
* 使用锁的方式
*/
Threadlocal http://blog.csdn.net/vking_wang/article/details/14225379
blog 2 http://www.iteye.com/topic/81936
ThreadLocal其实是采用哈希表的方式来为每个线程都提供一个变量的副本。从而保证各个线程间数据安全。每个线程的数据不会被另外线程访问和破坏。
JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序,ThreadLocal并
不是一个Thread,而是Thread的 局部变量
protected Object initialValue()
返回该线程 局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在 线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。
void set(Object value)
public void remove()
将当前线程 局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 1.5 新增的方法。需要指出的是,当线程结束后,对应该线程的 局部变量将自动被 垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
值得一提的是,在JDK5.0中,ThreadLocal已经支持 泛型,该类的类名已经变为ThreadLocal。API方法也相应进行了调整,新版本的API方法分别是void set(T value)、T get()以及T initialValue()。
ThreadLocal是如何做到为每一个线程维护 变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中定义了一个ThreadLocalMap,每一个Thread中都有一个该类型的变量——threadLocals——用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。
threadlocal 为 jdk1.2 提供解决多线程并发的一种新的思路
jdk1.5 新增 remove()移除当前局部变量的值
jdk5.0 threadlocal 已经支持繁星 threadloca对应的方法也进行了修改 void set(T value)、T get()以及T initialValue()。
比较
ThreadLocal和线程同步机制都是为了解决多线程中相同 变量的访问冲突问题。
帮助理解
个人理解,我们现在软件经常会分层,比如MVC ,类似这种横向分层,而ThreadLocal会提供一种方式,方便的在同一个线程范围内,提供一个存储空间,供我们使用,实现纵向的存储结构,便于我们在同一个线程范围内,随时取得我们在另外一个层面存放的数据。
用法三:在Runnable中创建ThreadLocal
还有一种用法是在线程类内部创建ThreadLocal,基本步骤如下:
1、在多线程的类(如ThreadDemo类)中,创建一个ThreadLocal对象threadXxx,用来保存线程间需要隔离处理的对象xxx。
2、在ThreadDemo类中,创建一个获取要隔离访问的数据的方法getXxx(),在方法中判断,若ThreadLocal对象为null时候,应该new()一个隔离访问类型的对象,并强制转换为要应用的类型。
3、在ThreadDemo类的run()方法中,通过调用getXxx()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。
Synchronized还是ThreadLocal?
ThreadLocal以空间换取时间,提供了一种非常简便的多线程实现方式。因为多个线程并发访问无需进行等待,所以使用 ThreadLocal会获得更大的性能。虽然使用ThreadLocal会带来更多的内存开销,但这点开销是微不足道的。因为保存在 ThreadLocal中的对象,通常都是比较小的对象。另外使用ThreadLocal不能使用原子类型,只能使用Object类型。 ThreadLocal的使用比synchronized要简单得多。
ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区 别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本, 使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通 信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂。