线程基础、线程之间的共享和协作
基础概念
- 进程:程序运行时资源分配的最小单位;进程内部多线程共享进程的资源。
- 线程:CPU调度的最小单位。
- 并发:处理多个任务的能力,不一定同时。
- 并行:同时处理多个任务的能力。
创建线程
- 继承Thread
- 实现Runnable
- Callable
关闭线程
- stop()
- resume()
- suspend()
上述三个方法关闭线程不推荐使用,因为线程不会释放资源,并可能造成死锁情况发生;因此推荐下述方法的使用。
interrupt() 中断线程,并非强制关闭,中断标志位置为true
isInterrupted() 判断当前线程是否中断
interrupted() 判断当前线程是否中断,中断标志位置为false
如果存在InterruptedException类型异常,标志位将被置为false
守护线程
守护线程中不要使用finally来关闭资源。因为守护线程为用户线程服务,不会退出JVM,任何代码(包括finally块)都不会在所有用户线程执行完成之后执行。
Volatile
原子操作:不可中断的一个或一系列操作。
volatile可以保证可见性,不一定保证原子性。
适用场景:只有一个线程写,其他线程读。
ThreadLocal
由于每个线程拥有一份数据副本,因此不会互相影响。而又因为每个线程均复制一份共享内存数据
因此不建议将大数据类型塞入ThreadLocal中。
等待和通知标准范式
等待:
获取对象的锁;
.循环里判断条件是否满足,不满足调用wait()方法;
条件满足执行业务逻辑。
通知:
获取对象的锁;
改变条件;
通知所有等待该对象的线程。
join()
线程A调用线程B的join方法,线程A等待线程B执行完毕再执行自己的逻辑。
yield()
线程执行到yield()以后,持有的锁不会释放。
sleep()
线程执行到sleep()以后,持有的锁不会释放。
wait()
调用方法前,必须持有锁,调用wait()方法之后,锁会被释放;当wait()方法返回的时候,线程会重新持有锁。
notify()、notifyAll()
调动方法之前必须持有锁,调用notify()、notifyAll()方法本身不会释放锁。
fork/join(分而治之)
数据量为n的问题,n<阈值,直接解决;n>阈值,将n分解为k个子问题,子问题间互相对立,与原问题形式相同,最后将子问题的解合并到原问题的解返回。
同步实现:ForkJoinPool的invoke()方法
异步实现:ForkJoinPool的execute()方法
并发工具类
CountDownLatch
用途:一个线程等待其他的线程完成工作以后再执行,加强版join
await()使线程等待,countDown()计数器减一
适用场景:某些数据需要初始化之后,业务线程才能正常执行的业务场景。
CyclicBarrier
用途:让一组线程到达某一个屏障时被阻塞,一直到组内线程均到达屏障,屏障解除,所有被阻塞线程会继续运行。
await()使线程等待
适用场景:线程协作,只有不同线程任务完成,业务才可以向下执行。
CountDownLatch和CyclicBarrier区别
1.CountDownLatch放行条件由第三者控制,CyclicBarrier放行条件由一组线程本身控制
2.CountDownLatch放行条件>=线程数,CyclicBarrier放行条件=线程数
Semaphore
控制同时访问特定资源的线程数量,多用于流量控制
适用场景:连接池资源控制;高并发场景限流。
Exchange
两个线程间进行数据交换
Future、FutureTask、Callable
Future接口定义方法
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
boolean cancel(boolean mayInterruptIfRunning)
尝试取消任务的执行,取消成功返回true,取消失败返回false;mayInterruptIfRunning表示是否允许中断正在执行的任务。
- 如果任务未开始,cancel返回true,并且任务永远不会被执行。
- 如果任务正在执行,且mayInterruptIfRunning为true,会调用中断逻辑,返回true;如果为false,不会调用线程中断,只是取消任务。
- 如果任务结束(正常完成、异常终止、被取消),返回false。
- 如果cancel()操作返回true,再调用isDone()、isCanceled()都返回true。
boolean isCancelled()
表示任务是否被取消成功,如果在任务正常完成前被取消成功,返回true。
boolean isDone()
表示任务是否已经完成,完成则返回true,注意:正常、异常或取消均代表任务完成。
V get()和V get(long timeout,TimeUnite unit)
- get()用来获取执行结果,这个方法会产生阻塞,直到任务执行完毕才返回。
- get(long timeout,TimeUnite unit)同样是用来获取执行结果,如果指定时间内没有取到结果,会抛出TimeoutException。
FutureTask部分代码
/* Possible state transitions:
* NEW -> COMPLETING -> NORMAL
* NEW -> COMPLETING -> EXCEPTIONAL
* NEW -> CANCELLED
* NEW -> INTERRUPTING -> INTERRUPTED
*/
private volatile int state;
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;
/** The underlying callable; nulled out after running */
private Callable<V> callable;
/** The result to return or exception to throw from get() */
private Object outcome; // non-volatile, protected by state reads/writes
/** The thread running the callable; CASed during run() */
private volatile Thread runner;
/** Treiber stack of waiting threads */
private volatile WaitNode waiters;
state是任务的运行状态
- 新建FutureTask,state处于NEW状态;COMPLETING和INTERRUPTING是两个中间状态,线程正常结束设置outcome属性前是COMPLETING,设置后变为NORMAL;当中断运行中线程的状态是INTERRUPTING,调用Thread.interuupt()后是INTERUUPTED;NORMAL代表顺利完成;EXCEPTIONAL代表过程出现异常;CANCELED代表执行过程被取消;INTERRUPTED被中断。
- 执行过程顺利完成:NEW -> COMPLETING -> NORMAL
- 执行过程出现异常:NEW -> COMPLETING -> EXCCEPTIONAL
- 执行过程被取消:NEW -> CANCELED
- 执行过程中,线程中断:NEW -> INTERRUPTING -> INTERRUPTED
callble是线程运行的有返回值的任务。
outcome是任务执行后的结果或异常。
waiters表示等待获取结果的阻塞线程,链表结构,后来线程会放在链表前面。
***更多资源关注公众号,不定时更新。***