基本概念
并发:在某个时间段内,多任务交替处理的能力。
并行:同时处理多任务的能力。
并发与并行的目标:尽肯能快的执行完所有任务。
并发特点:
-
并发程序之间有相互制约的关系。
(1)直接制约:一个程序需要另一个程序的结果。
(2)间接制约:程序间竞争共享资源。
处理器、缓冲区、磁盘IO等
- 并发程序的执行过程是断断续续的。
这与CPU的调度算法有关
- 并发数设置合理并且CPU拥有足够处理能力是,并发会提高程序的效率。
(1)在极端情况下,比如单核CPU,在单核的条件下,并发一般比串行效率要低,只要消耗在上下文切换–记忆现场和恢复现场等。
(2)防止阻塞:单核CPU下使用并发,主要是考虑防止阻塞。单核CPU使用单线程,如调用接口迟迟没有返回,那你的线程就一直阻塞,直到接口返回为止,但使用多线程就能防止这个问题,就算一个接口调用阻塞了,但并不影响其他线程的执行。
线程安全
- 线程状态
(1) new,新建状态,线程被创建且未启动的状态。
创建线程的三种方式:
a. extends Thread
b. implement Runnable
c. implement Callable
相比第一种,推荐第二种,因为继承不符合里氏代换原则;Runnable与Callable的不同点:
第一,call()方法具有返回值,前两种方式都有缺陷,即在任务执行完成后无法直接获取执行结果,需要借助共享变量获取。
第二,call()可以抛出异常。Runnable只能通过setDefaultUncaughtExceptionHandler()的方式才能在主线程中捕获到子线程的异常。
(2) runnable,就绪状态,调用start()之后运行之前的状态。
start()不能多次调用。
(3) running,运行状态,run()正在执行的状态。
时间、异常、锁、调度等会使线程退出running
(4)blocked,阻塞状态,以下情况会进入阻塞状态:
a.同步阻塞:锁被其他线程占用。
b.主动阻塞:调用Thread的某些方法,主动让出CPU执行权,如sleep()、join()等。
c.等待阻塞:wait()。
sleep与wait的相同点:sleep与wait都会使CPU让出执行权,不同点:sleep不会释放线程所占有的锁,wait会释放线程所占有的锁
。
(5)dead,终止状态,run()执行结束或者异常退出后的状态,此状态不可逆转。
-
线程安全
(1)数据单线程内可见。
线程局部变量
(2)只读对象。
条件:使用final修饰类,避免继承;使用private final修饰属性避免修改;没有任何的更新方法;返回值不能为可变对象的引用;
(3)线程安全类。
(4)同步与锁机制。
-
并发包
(1)线程同步类。
主要代表为CyclicBarrier、CountDownLatch、Semaphore等,逐步淘汰wait和notify同步方式。
(2)并发集合类。
主要代表ConcurrentHashMap(不断优化,从分段锁到CAS)、CopyOnWriteArrayList、BlockingQueue等。
(3)线程管理类。
线程池ThreadPoolExecutor
(4)锁相关类。
Lock,主要代表为ReentrantLock
《Easy Coding》读书笔记