问题
两个线程交替输出0到9
代码
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition1 = reentrantLock.newCondition();
Condition condition2 = reentrantLock.newCondition();
new Thread(()->{
reentrantLock.lock();
try {
for(int i = 1;i<10;i+=2){
condition2.await();
System.out.println("线程1:"+i);
condition1.signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
reentrantLock.unlock();
}
}).start();
new Thread(()->{
reentrantLock.lock();
try {
for(int i = 0;i<10;i+=2){
condition2.signal();
System.out.println("线程2:"+i);
condition1.await();
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
reentrantLock.unlock();
}
}).start();
}
结果
线程2:0
线程1:1
线程2:2
线程1:3
线程2:4
线程1:5
线程2:6
线程1:7
线程2:8
线程1:9
思考
之前介绍过线程是程序运行的最小单位,现在我们来深入学习一下线程的运行状态。
先看下线程的状态,JAVA的Thread类包含State枚举值
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 | 新建,未执行状态 |
RUNNABLE | 可执行,可能等待其他资源 |
BLOCKED | 阻塞,进入同步代码块前等待monitor锁 |
WAITING | 等待,等待特定动作唤醒 |
TIMED_WAITING | 时效等待,在规定时间内等待 |
TERMINATED | 完成,执行完毕 |
另外,说一下如何查看线程状态
1、查看所有java线程
Windows
jps
Linux
ps ef|grep java
2、查看指定线程状态
jstack -l [线程号]
线程控制
Synchronized与ReentrantLock
对比 | Synchronized | ReentrantLock |
---|---|---|
实现原理 | 锁升级 | CAS |
公平锁 | 不支持 | 支持 |
等待与唤醒 | wait(),notify() | await(),signal() |
Synchronized锁升级
在JDK1.5之前Synchronized加锁需要向操作系统申请,要经历 用户态->内核态->用户态的状态改变,因为大部分的锁都是统一效率比较底下。在JDK1.6以后Synchronized会根据当前线程并发量来上锁,随着并发量增大会有一个偏向锁(对象头,进程标记)->轻量级锁(CAS)->重量级锁(操作系统)的升级过程。
Synchronized类锁和对象锁
类锁,不同线程进入不同对象的同步方法块可能产生阻塞
synchronized(Object.class){
}
对象锁,不同线程进入同一个对象的同步方法块可能产生阻塞
synchronized(this){
}
范式
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
try {
//逻辑
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
reentrantLock.unlock();
}
死锁
必要条件:互斥 不可剥夺 请求和保持 循环等待
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition1 = reentrantLock.newCondition();
Condition condition2 = reentrantLock.newCondition();
new Thread(()->{
reentrantLock.lock();
try {
condition2.await();
condition1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
reentrantLock.unlock();
}
}).start();
new Thread(()->{
reentrantLock.lock();
try {
condition1.await();
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
reentrantLock.unlock();
}
}).start();
}
查看线程状态
"Thread-1" #15 prio=5 os_prio=0 tid=0x000000001e939000 nid=0x3524 waiting on condition [0x000000001f21f000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007763a07d8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at TestThread.lambda$main$1(TestThread.java:28)
at TestThread$$Lambda$2/157627094.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"Thread-0" #14 prio=5 os_prio=0 tid=0x000000001e92f800 nid=0x58e4 waiting on condition [0x000000001f11e000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007763a07f0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at TestThread.lambda$main$0(TestThread.java:15)
at TestThread$$Lambda$1/672320506.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
WAITING、BLOCK状态会释放CPU资源。