- 1、线程的生命周期
- 1.1、JDK 中用 Thread.State 枚举表示了线程的几种状态
- 1.2、线程状态转换图
- 1.3、查看线程状态
- 2、线程的同步
- 2.1、问题引出
- 2.2、Synchronized
- 2.2.1、线程同步机制
- 2.2.2、同步具体方法 - Synchronized
- 2.2.3、分析同步原理
- 3、互斥锁
- 3.1、基本介绍
- 3.2、使用互斥锁来解决售票问题
- 3.3、注意事项和细节
- 4、线程的死锁
- 4.1、基本介绍
- 4.2、形象的比喻
- 4.3、代码实现
- 5、释放锁
- 5.1、下面操作会释放锁
- 5.2、下面操作不会释放锁
package state_;
public class ThreadState_ {
public static void main(String[] args) throws InterruptedException {
T t = new T();
System.out.println(t.getName() + "状态: " + t.getState()); // Thread-0状态: NEW
t.start();
while (Thread.State.TERMINATED != t.getState()) {
System.out.println(t.getName() + "状态: " + t.getState());
Thread.sleep(500);
}
System.out.println(t.getName() + "状态: " + t.getState()); // Thread-0状态: TERMINATED
}
}
class T extends Thread {
@Override
public void run() {
while (true) {
for (int i = 0; i < 10; i++) {
System.out.println("hi " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
}
}
2、线程的同步
2.1、问题引出
2.2、Synchronized
2.2.1、线程同步机制
2.2.2、同步具体方法 - Synchronized
2.2.3、分析同步原理
3、互斥锁
3.1、基本介绍
3.2、使用互斥锁来解决售票问题
package syn;
public class SellTicket {
public static void main(String[] args) {
// 测试
// 测试一把
SellTicket03 sellTicket03 = new SellTicket03();
new Thread(sellTicket03).start(); // 第1个线程-窗口
new Thread(sellTicket03).start(); // 第2个线程-窗口
new Thread(sellTicket03).start(); // 第3个线程-窗口
}
}
// 实现接口方式, 使用synchronized实现线程同步
class SellTicket03 implements Runnable {
private int ticketNum = 100; // 让多个线程共享 ticketNum
private boolean loop = true; // 控制run方法变量
Object object = new Object();
// 同步方法(静态的)的锁为当前类本身
// 解读
// 1. public synchronized static void m1() {} 锁是加在 SellTicket03.class
// 2. 如果在静态方法中, 实现一个同步代码块
public synchronized static void m1() {
}
public static void m2() {
synchronized (SellTicket03.class) {
System.out.println("m2");
}
}
// 1. public synchronized void sell() {} 就是一个同步方法
// 2. 这时锁在 this对象
// 3. 也可以在代码块上写 synchronize, 同步代码块, 互斥锁还是在this对象
public void sell() { // 同步方法, 在同一时刻, 只能有一个线程来执行sell方法
synchronized (object) {
if (ticketNum <= 0) {
System.out.println("售票结束...");
loop = false;
return;
}
// 休眠50毫秒, 模拟
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"
+ " 剩余票数=" + (--ticketNum));
}
}
@Override
public void run() {
while (loop) {
sell(); // sell方法是一共同步方法
}
}
}
class SellTicket01 extends Thread {
private static int ticketNum = 100; // 让多个线程共享 ticketNum
@Override
public void run() {
while (true) {
if (ticketNum <= 0) {
System.out.println("售票结束...");
break;
}
// 休眠50毫秒, 模拟
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum));
}
}
}
// 实现接口方式
class SellTicket02 implements Runnable {
private int ticketNum = 100; // 让多个线程共享 ticketNum
@Override
public void run() {
while (true) {
if (ticketNum <= 0) {
System.out.println("售票结束...");
break;
}
// 休眠50毫秒, 模拟
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum));
}
}
}
3.3、注意事项和细节
4、线程的死锁
4.1、基本介绍
4.2、形象的比喻多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程是一定要避免死锁的发生
4.3、代码实现妈妈:你先完成作业,才让你玩手机
小明:你先让我玩手机,我才完成作业
package syn;
public class DeadLock_ {
public static void main(String[] args) {
// 模拟死锁现象
DeadLockDemo A = new DeadLockDemo(true);
A.setName("A 线程");
DeadLockDemo B = new DeadLockDemo(false);
B.setName("B 线程");
A.start();
B.start();
// 控制台输出
}
}
// 线程
class DeadLockDemo extends Thread {
static Object o1 = new Object(); // 保证多线程, 共享一个对象,这里使用 static
static Object o2 = new Object();
boolean flag;
public DeadLockDemo(boolean flag) { // 构造器
this.flag = flag;
}
@Override
public void run() {
// 下面业务逻辑的分析
// 1. 如果 flag 为 T, 线程 A 就会先得到/持有 o1 对象锁, 然后尝试去获取 o2 对象锁
// 2. 如果线程 A 得不到 o2 对象锁, 就会 Blocked
// 3. 如果 flag 为 F, 线程 B 就会先得到/持有 o2 对象锁, 然后尝试去获取 o1 对象锁
// 4. 如果线程 B 得不到 o1 对象锁,就会 Blocked
if (flag) {
synchronized (o1) { // 对象互斥锁, 下面就是同步代码
System.out.println(Thread.currentThread().getName() + " 进入 1");
synchronized (o2) { // 这里获得 li 对象的监视权
System.out.println(Thread.currentThread().getName() + " 进入 2");
}
}
} else {
synchronized (o2) {
System.out.println(Thread.currentThread().getName() + " 进入 3");
synchronized (o1) { // 这里获得 li 对象的监视权
System.out.println(Thread.currentThread().getName() + " 进入 4");
}
}
}
}
}
5、释放锁
5.1、下面操作会释放锁
5.2、下面操作不会释放锁



