标签:调用 href 一个 数据 链表 jstack 退出 干什么 周期性任务
wait/notify必须存在于synchronized块中。
volatile
多线程的内存模型:main memory(主存)、working memory(线程栈),在处理数据时,线程会把值从主存load到本地栈,完成操作后再save回去(volatile关键词的作用:每次针对该变量的操作都激发一次load and save)
Thread类最佳实践: 写的时候最好要设置线程名称 Thread.name,并设置线程组 ThreadGroup,目的是方便管理。在出现问题的时候,打印线程栈 (jstack -pid) 一眼就可以看出是哪个线程出的问题,这个线程是干什么的。
如何获取线程中异常
Thread t = new Thread(task);
t.setUncaughtException(new UncaughtExceptionHandler(){...});
t.start();
不能用try,catch来获取线程中的异常
Future和FutureTask
Future是接口,FutureTask是类
Future表示一个异步计算的结果. 异步计算是在其他线程进行的, 因此异步计算的结果, 有可能有值, 也有可能没有值. 于是, Future就提供了一些方法来处理这种未知状态:
a. isDone() 异步任务是否完成, 即否有结果
b. get() 获取异步任务结果, 如果异步任务未完成, 此方法会一直阻塞, 直到异步方法完成 或 任务被取消 (调用了cancel()方法)
c. cancel() 取消异步任务, 如果异步任务已经完成, 那么取消失败(即cancel()方法返回false)
d. isCancelled() 查询异步任务是否已被取消
FutureTask就是一个可取消的异步任务,FutureTask实现了两个接口,Runnable和Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值,那么这个组合的使用有什么好处呢?假设有一个很耗时的返回值需要计算,并且这个返回值不是立刻需要的话,那么就可以使用这个组合,用另一个线程去计算返回值,而当前线程在使用这个返回值之前可以做其它的操作,等到需要这个返回值时,再通过Future得到
//1
FutureTask<Integer> future = new FutureTask<Object>(callable);
new Thread(future).start();
//这里可以做其他事情
future.get();//阻塞获得结果
//2
public void function() {
// 1. init services
final ExecutorService executorService = ...
// 2. make task
FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
String result = "";
//do something;
return result;
}
});
// 3. submit task
executorService.submit(futureTask);
// 4. get result
String result = futureTask.get();
// 5. do something with result
// ...
}
ThreadLocal类
用处:保存线程的独立变量。对一个线程类(继承自Thread) 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。常用于用户登录控制,如记录session信息。
实现:每个Thread都持有一个TreadLocalMap类型的变量(该类是一个轻量级的Map,功能与map一样,区别是桶里放的是entry而不是entry的链表。功能还是一个map。)以本身为key,以目标为value。 主要方法是get()和set(T a),set之后在map里维护一个threadLocal -> a,get时将a返回。ThreadLocal是一个特殊的容器。
cas和aba
CAS:对于内存中的某一个值V,提供一个旧值A和一个新值B。如果提供的旧值V和A相等就把B写入V。这个过程是原子性的。
CAS执行结果要么成功要么失败,对于失败的情形下一班采用不断重试。或者放弃。
ABA:如果另一个线程修改V值假设原来是A,先修改成B,再修改回成A。当前线程的CAS操作无法分辨当前V值是否发生过变化。
如何解决ABA问题? 通常是使用版本戳来解决这个问题,避免并发中的问题。 CAS是一种乐观锁技术
重排序/happens before
JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before关系。
happen-before原则是JMM中非常重要的原则,它是判断数据是否存在竞争、线程是否安全的主要依据,保证了多线程环境下的可见性。
happen-before原则解决了重排序带来的多线程运行问题。
如果两个操作之间具有happens-before 关系,那么前一个操作的结果就会对后面一个操作可见。
happens-before原则规则:
线程池
Java通过Executors提供四种线程池,分别为:
(缓存、固定、定时、单例)
标签:调用 href 一个 数据 链表 jstack 退出 干什么 周期性任务
原文地址:http://www.cnblogs.com/webCrazy/p/7452435.html