能够写出高伸缩性的并发是一门艺术
在JAVA SE5中新增了3个包
- java.util.concurrent
- java.util.concurrent.atomic
- java.util.concurrent.locks
在java的内存模型中,类的实例字段、静态字段和构成数组的对象元素都会被多个线程所共享,局部变量与方法参数都是线程私有的,不会被共享。
每个线程都有自己的工作内存(高速缓冲区),共享主内存的数据。线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,不能直接读写主内存的变量。不同的线程也无法访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。
volatile保证新值能能立即同步到主内存,以及每次使用前即从住内存刷新
禁止指令重排(机器及的优化操作)
线程是cpu调度的基本单位,java语言提供了在不同硬件和操作系统平台下对线程操作的统一处理。
实现线程主要有3中方式:使用内核线程实现、使用用户线程实现和使用用户线程加轻量级进程混合实现。
不同虚拟机不同实现
java使用线程调度方式是抢占式的
线程状态:
- 新建:创建后尚未启动的线程处于这种状态
- 运行:Runable包含了操作系统线程状态中的Running和Ready,也就是处于此状态的线程有可能正在执行,也有可能正在等待cpu为它分配执行时间
- 无限期等待:不会分配cpu执行时间,他们等待被其他线程显示的唤醒,没有设置Timeout的Object.wait()和Thread.join()、LockSupport.park()
- 限期等待:也不会分配cpu执行事件,不过无需等待被其他线程显示的唤醒,一定时间后自动唤醒,Thread.sleep()、设置了参数的Object.wait()和Thread.join()、LockSupport.parkNanos()、LockSupport.parkUntil()。
- 阻塞:阻塞在等待获得一个排他锁
- 结束:以终止的线程状态,线程已经结束执行。
要保证线程安全,并不一定要进行同步,两者没有因果关系,同步知识保证共享数据争用时的正确手段,
synchronized修饰方法,锁是当前对象。静态的方法锁的是Class对象 。获取锁操作的粒度是线程。
// 恢复被中断的状态
Thread.currentThread().interrupt();
java.util.concurrent
这个包下有并发容器、和线程池
减少锁竞争:
- 缩小锁的范围(快进快出)
- 减小锁的粒度(通过所分解技术:将一个锁分解为两个锁)
- 锁分段
- 避免热点域
并发容器:http://flyouwith.iteye.com/blog/2206550
同步工具类:http://flyouwith.iteye.com/blog/2206610
线程池:http://flyouwith.iteye.com/blog/2206623
Thread对象表示的线程和Runnable对象表示的线程所执行的任务之间是紧耦合的。这对于小型应用程序来说没问题,但对于大规模并发应用来说,合理的做法是将线程的创建与管理和程序的其他部分分离开。封装这些功能的对象就是执行器
-
执行器接口定义了三种类型的执行器对象。
-
线程池是最常见的一种执行器的实现。
-
Fork/Join是JDK 7中引入的并发框架。
- Executor,一个运行新任务的简单接口。
- ExecutorService,扩展了Executor接口。添加了一些用来管理执行器生命周期和任务生命周期的方法。
- ScheduledExecutorService,扩展了ExecutorService。支持Future和定期执行任务。
java.util.concurrent.atomic
可以对boolean 、int、 long、引用(V value)进行原子操作。
采用CAS(compareAndSwap)比较 交换的策略。原子操作,当且紧当内存地址中的值符合旧的预期值时,处理器用新值更新旧值。
java.util.concurrent.locks
一种简单的可重入锁它们有能力收回获得锁的尝试。如果当前锁对象不可用,或者锁请求超时(如果超时时间已指定),tryLock方法会收回获取锁的请求。如果在锁获取前,另一个线程发送了一个中断,lockInterruptibly方法也会收回获取锁的请求
public class RunMain {
static class Test {
private Lock lock = new ReentrantLock();
/**
* 获得锁
*/
public boolean isLock(Test t) {
boolean b1 = false;
boolean b2 = false;
try {
b1 = lock.tryLock();
b2 = t.lock.tryLock();
} finally {
if (!(b1 && b2)) {
if (b1)
lock.unlock();
if (b2)
t.lock.unlock();
}
}
return b1 && b2;
}
public void method1(Test t) {
if (isLock(t)) {
try {
t.method2();
} finally {
System.err.println("执行成功释放锁");
t.lock.unlock();
lock.unlock();
}
}else{
System.out.println("没有获得锁");
}
}
public void method2() {
System.err.println("-------");
}
}
static class ThreadRun implements Runnable {
private Test test;
private Test test2;
public ThreadRun(Test test, Test test2) {
this.test = test;
this.test2 = test2;
}
Random random = new Random();
@Override
public void run() {
while(true){
try{
Thread.sleep(random.nextInt(10));
}catch(InterruptedException e){}
test.method1(test2);
}
}
}
public static void main(String[] args) {
Test test1 = new Test();
Test test2 = new Test();
Thread t1 = new Thread(new ThreadRun(test1, test2));
Thread t2 = new Thread(new ThreadRun(test2, test1));
t1.start();
t2.start();
}
}