1,什么是线程安全性?
简单概括就是一个类在多线程情况下能安全调用就是线程安全
2,Servlet 的线程安全性
默认是非线程安全的,写servlet代码的时候需要注意线程安全,注意同步
3,volatile
volatile实际上是保证了多线程情况下,有读取,有写入,保证了读取的都是最新的值。
开发中一般boolean值 开关灯用它定义。
volatile的原理如下:不用volatile修饰的变量再多线程情况下, 每个线程会有一个变量从内存备份放在cpu储存上,每次都是读取这个备份的值
但是用volatile修饰的变量,强制要求线程每次都存内存读取,一旦一个线程修改了,会立刻更新到内存上,
同时volatile还有个作用,防止指令重排
4,多线程可能有的问题
死锁:多个线程竞争共享资源,每个线程都处于堵塞状态,都不结束
饿死:资源等待时间过长,资源被贪婪线程长期占用不释放,其他线程就处于饿死状态
活锁:一个线程经常对另一个线程的操作作出响应,如果另一个线程的操作也对这个线程的操作作出响应,那么就可能导致活锁(livelock)。
5.ThreadLocal
为每一个线程提供一个本地变量,有一个初始值可以定义匿名子类重写,方法名字为initialValue,有set和get方法。
实现原理为:把当前“线程对象”当作键,变量作为值存储在一个 Map 中
1 private T setInitialValue() { 2 T value = initialValue(); 3 Thread t = Thread.currentThread(); 4 ThreadLocalMap map = getMap(t); 5 if (map != null) 6 map.set(this, value); 7 else 8 createMap(t, value); 9 return value; 10 }
同时常见的例子,使用ThreadLoca可以解决simpleDateFormat的多线程安全和资源消耗的问题
1 package com.peidasoft.dateformat; 2 3 import java.text.DateFormat; 4 import java.text.ParseException; 5 import java.text.SimpleDateFormat; 6 import java.util.Date; 7 8 public class ConcurrentDateUtil { 9 10 private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() { 11 @Override 12 protected DateFormat initialValue() { 13 return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 14 } 15 }; 16 17 public static Date parse(String dateStr) throws ParseException { 18 return threadLocal.get().parse(dateStr); 19 } 20 21 public static String format(Date date) { 22 return threadLocal.get().format(date); 23 } 24 }
也可以不重写匿名类,获取get的时候判断是不是空
1 package com.peidasoft.dateformat; 2 3 import java.text.DateFormat; 4 import java.text.ParseException; 5 import java.text.SimpleDateFormat; 6 import java.util.Date; 7 8 public class ThreadLocalDateUtil { 9 private static final String date_format = "yyyy-MM-dd HH:mm:ss"; 10 private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(); 11 12 public static DateFormat getDateFormat() 13 { 14 DateFormat df = threadLocal.get(); 15 if(df==null){ 16 df = new SimpleDateFormat(date_format); 17 threadLocal.set(df); 18 } 19 return df; 20 } 21 22 public static String formatDate(Date date) throws ParseException { 23 return getDateFormat().format(date); 24 } 25 26 public static Date parse(String strDate) throws ParseException { 27 return getDateFormat().parse(strDate); 28 } 29 }