并发编程
CPU时间片轮转机制:又称RR调度,会导致上下文切换
什么是进程和线程
进程:程序运行资源分配的最小单位,进程内部有多个线程,会共享这个进程的资源
线程:CPU调度的最小单位,必须依赖进程而存在。
并行和并发
并行:同一时刻,可以同时处理事情的能力
并发:与单位时间相关,在单位时间内可以处理事情的能力
调用一个线程的interrupt() 方法中断一个线程,并不是强行关闭这个线程,只是跟这个线程打个招呼,将线程的中断标志位置为true,线程是否中断,由线程本身决定。
isInterrupted() 判定当前线程是否处于中断状态。
static方法interrupted() 判定当前线程是否处于中断状态,同时中断标志位改为false。
方法里如果抛出InterruptedException,线程的中断标志位会被复位成false,如果确实是需要中断线程,要求我们自己在catch语句块里再次调用interrupt()。
run()和start() :run方法就是普通对象的普通方法,只有调用了start()后,Java才会将线程对象和操作系统中实际的线程进行映射,再来执行run方法。
yield() :让出cpu的执行权,将线程从运行转到可运行状态,但是下个时间片,该线程依然有可能被再次选中运行。
notify和notifyAll应该用谁?
应该尽量使用notifyAll,使用notify因为有可能唤醒的是其他线程,发生信号丢失的的情况。wait和notify基于同个对象上操作,调用wait方法后,此线程会进入等待状态,等待被唤醒
join()方法
线程A,执行了线程B的join方法,线程A必须要等待B执行完成了以后,线程A才能继续自己的工作,join内部方法为wait
调用yield() 、sleep()、wait()、notify()等方法对锁有何影响?
线程在执行yield()以后,持有的锁是不释放的
sleep()方法被调用以后,持有的锁是不释放的
调动方法之前,必须要持有锁。调用了wait()方法以后,锁就会被释放,当wait方法返回的时候,线程会重新持有锁
调动方法之前,必须要持有锁,调用notify()方法本身不会释放锁的
Fork-Join
规模为N的问题,N<阈值,直接解决,N>阈值,将N分解为K个小规模子问题(拆到不能再拆),子问题互相对立,与原问题形式相同,将子问题的解join得到原问题的解
工作密取:当线程A已经完成了分配给他的所有子任务,线程B还没有完成时,线程A会从线程B的任务中抽取部分任务执行(从任务后面开始),从而减少整个大任务的执行时间
MyTask extends RecursiveTask/RecursiveAction/ForkJoinTask
常用的并发工具类
CountDownLatch
作用:是一组线程等待其他的线程完成工作以后在执行,加强版join
await用来等待,countDown负责计数器的减一
原理:内部类Sync extends AbstractQueuedSynchronizer
初始CountDownLatch数量即为设置aqs的state值,countDown方法使用cas进行减一操作,await方法循环判断state值是否为0,不为0则通过LockSupport的pack方法进行阻塞,为0则通过LockSupport的unpark方法唤醒线程继续执行
CyclicBarrier
让一组线程达到某个屏障,被阻塞,一直到组内最后一个线程达到屏障时,屏障开放,所有被阻塞的线程会继续运行CyclicBarrier(int parties)
CyclicBarrier(int parties, Runnable barrierAction),屏障开放,barrierAction定义的任务会执行
原理:假设parties数量为2,线程thread1和线程thread2都执行到CyclicBarrier的await(),都进入dowait(boolean timed, long nanos),thread1先获取到独占锁,执行到–count的时,index等于1,所以进入下面的for循环,接着执行trip.await(),进入await()方法,执行Node node = addConditionWaiter()将当前线程构造成Node节点并加入到Condition等待队列中,然后释放获取到的独占锁,当前线程进入阻塞状态(LockSupport.park);此时,线程thread2可以获取独占锁,继续执行–count,index等于0(此时已满足CyclicBarrier数量条件,所以当前线程不用加入到Condition等待队列中进行阻塞),直接先执行barrierAction任务,即command.run(),然后执行nextGeneration(),AQS的doSignalAll(Node node)方法,从Condition等待队列中的头结点开始释放节点,唤醒节点对应的线程(LockSupport.unpark),即thread1恢复执行。
CountDownLatch和CyclicBarrier辨析
1、countdownlatch放行由第三者控制,CyclicBarrier放行由一组线程本身控制
2、countdownlatch放行条件》=线程数,CyclicBarrier放行条件=线程数
Semaphore
控制同时访问某个特定资源的线程数量,用在流量控制
Exchange
两个线程间的数据交换
Callable、Future和FutureTask
isDone,结束,正常还是异常结束,或者自己取消,返回true;
isCancelled 任务完成前被取消,返回true;
cancel(boolean):
1、任务还没开始,返回false
2、任务已经启动,cancel(true),中断正在运行的任务,中断成功,返回true,cancel(false),不会去中断已经运行的任务
3、任务已经结束,返回false