一、线程创建方式
1、继承thread类
①、定义一个线程子类
②、重写thread的run
③、实例化一个对象,调用star()方法
public class java_threadone extends Thread {
public static void main(String[] args){
(new java_threadone()).start();
System.out.println("main thread run");
}
public synchronized void run(){
System.out.println("sub thread run");
}
}
2、实现runable
实现runable接口的run()方法
public class java_threadtwo implements Runnable {
public static void main(String[] args){
(new Thread(new java_threadtwo())).start();
System.out.println("main thread run");
}
public void run() {
System.out.println("sub thread run");
}
}
thread与runable的关系:
class Thread implements Runnable
所以,thread类的run()方法实现runable接口的run()方法,见thread类的源码
@Override public void run() { if (target != null) { target.run(); } }
private Runnable target;
二、线程安全—ThreadLocal & synchronized
1、ThreadLocal
ThreadLocal类:当多个线程使用同一个局部变量时,ThreadLocal给每个线程提供独立的变量副本,使每个线程对自身的副本操作不会影响其他的线程所对应的副本,threadlocal通过K(存放线程) & Value(存放局部 变量)的方式包括每个线程对应的Value值。-----以空间换时间
该类有四个方法:
set()方法:设置当前线程的局部变量值;源码
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
get()方法:返回当前线程的局部变量值;源码
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
remove()方法:将当前线程局部变量的值删除,目的是减少内存的占用;当线程结束后,对应该线程的局部变量将自动被垃圾回收;
initialValue()方法:返回该线程局部变量的初始值,是一个protected方法。
2、synchronized
同步锁,把需要同步的方法或者代码块包装在它内部,这样所有线程对这块区域的代码访问必须先持有锁才能进入,否则拦截在外面等待正在持有锁的线程处理完毕再获取锁进入。——以时间换空间
public void output(String name){
int len = name.length();
synchronized (Outputer.class)
{
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
3、二者对比
以空间换时间---为每个线程提供一份变量,多开销内存,但是线程不用等待,可以一起执行而相互之间没有影响;
以时间换空间---某个区域的代码或者变量只有一份,节省了内存,但是会有其他线程等待的现象,浪费了时间但是节约了空间;
ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发 性。