-
什么是线程,什么是进程
进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,拥有独立的内存单元,是一个动态概念,竞争计算机系统资源的基本单位。
线程:是进程的一个执行单元,是进程内的调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位 -
线程状态转换
从jdk代码中,可以看出,对线程定义的状态有如下几种:
JDK代码:/** * A thread state. A thread can be in one of the following states: * <ul> * <li>{@link #NEW}<br> * A thread that has not yet started is in this state. * </li> * <li>{@link #RUNNABLE}<br> * A thread executing in the Java virtual machine is in this state. * </li> * <li>{@link #BLOCKED}<br> * A thread that is blocked waiting for a monitor lock * is in this state. * </li> * <li>{@link #WAITING}<br> * A thread that is waiting indefinitely for another thread to * perform a particular action is in this state. * </li> * <li>{@link #TIMED_WAITING}<br> * A thread that is waiting for another thread to perform an action * for up to a specified waiting time is in this state. * </li> * <li>{@link #TERMINATED}<br> * A thread that has exited is in this state. * </li> * </ul> * * <p> * A thread can be in only one state at a given point in time. * These states are virtual machine states which do not reflect * any operating system thread states. * * @since 1.5 * @see #getState */ public enum State { /** * Thread state for a thread which has not yet started. */ NEW, /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */ RUNNABLE, /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */ BLOCKED, /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }
线程状态:
状态 描述 NEW(新建) 线程新建但是还没有start的时候,即 new Thread()
RUNNABLE(就绪) 调用了 Thread
的start()
方法,此时线程可运行,但是也有可能需要等待其他操作系统资源,比如处理器资源,当获取到处理器资源之后,则进入RUNNING状态BLOCKED(阻塞) 当进入同步代码块时,如果需要等待获取锁,那么就会被阻塞进入该状态 WAITING(等待) 由于执行了 Object.wait()
、Thread.join()
、LockSupport.park()
进入了等待状态TIMED_WAITING(有限时长等待) 由于执行了 Thread.sleep
、Object.wait(long)
、Thread.join(long)、LockSupport.parkNanos
、LockSupport.parkUntil
,进入了有限时长的等待状态TERMINATED(结束) 线程run方法执行结束 各状态转换如下:
-
为何使用线程池,线程池的原理
好处: 线程是一个资源,切换上下文也需要消耗资源,利用线程池可以减少线程的创建和线程的上下文切换,节约资源。
原理: 详见ThreadPoolExecutor
-
手写生产者消费者模型
- 基于
BlockingQueue
实现class Producer implements Runnable { private final BlockingQueue queue; Producer(BlockingQueue q) { queue = q; } public void run() { try { while (true) { queue.put(produce()); } } catch (InterruptedException ex) { ... handle ...} } Object produce() { ... } } class Consumer implements Runnable { private final BlockingQueue queue; Consumer(BlockingQueue q) { queue = q; } public void run() { try { while (true) { consume(queue.take()); } } catch (InterruptedException ex) { ... handle ...} } void consume(Object x) { ... } } class Setup { void main() { BlockingQueue q = new SomeQueueImplementation(); Producer p = new Producer(q); Consumer c1 = new Consumer(q); Consumer c2 = new Consumer(q); new Thread(p).start(); new Thread(c1).start(); new Thread(c2).start(); } }
- 基于notify/wait()实现
// todo: 添加对应代码
- 基于lock实现
// todo: 添加对应代码
- 基于
-
实现同步的方式及其区别
synchronized
&ReentrantLock
-
都是可重入锁;
可重入锁: 可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者class),这样的锁就叫做可重入锁 -
ReentrantLock
支持更多特性:
可等待,可中断,可多条件,可公平锁公平锁: 加锁前先查看是否有排队等待的线程,有的话优先处理排在前面的线程,先来先得。
非公平所: 线程加锁时直接尝试获取锁,获取不到就自动到队尾等待。ReentrantLock
非公平锁的实现:static final class NonfairSync extends Sync { final void lock() { // 非公平锁实现,获取锁时不是直接添加到队列末尾,而是先尝试获取锁 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else // 不成功的话走正常获取锁的流程,将其加入到队列排队 acquire(1); } // 省略部分代码... }
-
-
JAVA锁(synchronized)内部实现原理,JVM的锁优化有哪些
原理:
synchronized
在经过编译后,会在同步块的前后形成monitorenter
和monitorexit
两个字节码命令。者两个字节码都需要一个reference类型的参数来指明需要加锁的对象(对象实例或者Class对象的)。
并且规定synchronized
是可重入的,执行monitorenter
需要先尝试获取对象的锁,如果该对象未被锁定或者当前线程已经拥有该对象的锁,那么锁的计数器加一;monitorexit
则相反,计数器减一,当计数器为0时锁才会被释放。JVM的锁优化:
锁消除: 返现如果只有一个线程使用或者无需加锁的时候,直接消除锁
锁粗化: 扩大加锁范围
自旋锁: 没有获取到锁的时候自旋等待(消耗CPU),省去了线程的上下文切换;当竞争特别激烈的时候该优化不一定就好了。
自适应锁: 在自旋锁的基础上,智能的调控自旋的次数或时间
轻量级锁: 在没有多线程竞争的前提下,利用CAS ,减少传统的重量级锁使用操作系统互斥量产生的性能消耗
偏向锁: 当一个线程获取锁后,在其他线程获取锁之前,该线程再次进入加锁代码块时无需再次获取锁;
但是当有另一个线程来获取该锁时,偏向锁便不再生效。
偏向所->轻量级锁->重量级锁 -
无锁并发
// todo
-
AQS的实现原理
请看另一篇博文: JAVA并发编程: CAS和AQS -
volatile的理解
volatile具有可见性和有序性,但是不具有原子性
适用场景:
适用于对变量的写操作不依赖于当前值,对变量的读取操作不依赖于非volatile变量。
(eg. 通常用做某类状态标志)具体jvm是如何实现volatile的可参考: 《深入理解Java虚拟机 JVM高级特性与最佳实践》中将JMM的。
12.3.3–对于volatile型变量的特殊规则 -
JAVA线程池: ThreadPoolExecutor
可以参考下JAVA线程池原理详解一
主要需要了解到如下问题:- 为何需要使用到线程池
- ThreadPoolExecutor构造函数中各属性的理解
- 线程池中对线程的管理,何时创建,何时回收
- 线程池中任务队列的类型和区别(
SynchronousQueue
,LinkedBlockingQueue
,ArrayBlockingQueue
) - 几种拒绝策略的区别(
AbortPolicy
,CallerRunsPolicy
,DiscardPolicy
,DiscardOldestPolicy
) - 如何确定coreSize和maxSize的大小
待续