深入浅出谈java进阶——多线程
多线程
线程的 5 个状态的理解:
1. 新建,刚刚新建的线程,还未进入就绪队列
2. 就绪,进入就绪队列的线程拥有了获得 CPU 时间的机会,但不是一定会马上执行,与线程调度有关。
3. 运行,获得了 CPU 时间,正在被执行的线程。
4. 阻塞,进入阻塞状态的线程只是暂时失去了 CPU 时间,该类线程没有结束,“阻塞态”的线程只能进入到“就绪态”。
5. 死亡,死亡的线程即彻底结束了。
1.线程同步
CountDownLatch 一个或多个线程等待其他线程完成一系列操作后才执行
CyclicBarrier 多个线程互相等待,直到到达同一个同步点,再继续一起执行。适用于多个线程有固定的多步需要执行,线程间互相等待,当都执行完了,在一起执行下一步。
Phaser; 与cyclicbarrier类似,功能更强。它支持任务在多个点都进行同步,支持动态调整注册任务的数量
Exchanger 可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据,当线程A调用Exchange对象的exchange()方法后,他会陷入阻塞状态,直到线程B也调用了exchange()方法,然后以线程安全的方式交换数据,之后线程A和B继续运行
Semaphore: 可以控制同时访问的线程个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可; 比如多个窗口叫号,窗口都忙时,顾客等待,有空闲时,最新等待的被通知
任务1:理解,通过看源码
任务2:通过练习demo,加深理解
任务3:区分各种使用场合
2.Java 8使用CompletableFuture编写异步任务
CompletableFuture类的一系列aync结尾的方法,可以启动一个异步任务,既可以在默认的线程池运行,也可以指定线程池。CompletableFuture类也包含了对CompletableFuture的各种组合(then开头的方法)、结果获取的方法。 例如,异步地通过网址获取链接集,然后再异步地下载链接集的文本内容
任务1:对比CompletableFuture和Future
任务2:练习demo
3.线程thread.interrupt()
4.Thread.sleep/Object.wait区别
sleep()方法
阻塞——sleep()使当前线程进入停滞状态(阻塞当前线程),让出CUP的使用、目的是不让当前线程独自霸占该进程所获的CPU资源,以留一定时间给其他线程执行的机会;
不释放锁——sleep()是Thread类的Static(静态)的方法;因此他不能改变对象的机锁,所以当在一个Synchronized块中调用Sleep()方法是,线程虽然休眠了,但是对象的机锁并木有被释放,其他线程无法访问这个对象(即使睡着也持有对象锁)。
不立刻执行——在sleep()休眠时间期满后,该线程不一定会立即执行,这是因为其它线程可能正在运行而且没有被调度为放弃执行,除非此线程具有更高的优先级。
wait()方法
释放锁——wait()方法是Object类里的方法;当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时失去(释放)了对象的机锁(暂时失去机锁,wait(long timeout)超时时间到后还需要返还对象锁);其他线程可以访问;
notify唤醒——wait()使用notify或者notifyAlll或者指定睡眠时间来唤醒当前等待池中的线程。
synchronized 中——wait()必须放在synchronized block中,否则会在program runtime时扔出”java.lang.IllegalMonitorStateException“异常。
5.Volatile和AtomicInteger,AtomicIntegerArray线程安全操作
新增一个AtomicIntegerArray的getAndAdd()方法的考察
(1)getAndAdd()方法返回索引所在未知的数值,并把该位置的值增加一个Delta数值回填到索引位置
(2)所以value的值是默认的2,而变更后的数值是2+5=7
01publicclass Test {02privatestaticint[] arr =newint[]{1, 2, 3};03privatestaticAtomicIntegerArray integerArray =new AtomicIntegerArray(arr);04 05publicstaticvoid main(String[] args) {06intvalue = integerArray.getAndAdd(1, 5);07 System.out.println(integerArray.get(1));08 System.out.println(value);09 }10 }