多线程(死锁、等待与唤醒)
一、死锁(面试)
代码实现:
// 实现死锁机制
public class MyRunnable implements Runnable {
public static String lockA = "A锁";
public static String lockB = "B锁";
@Override
public void run() {
while (true) {
synchronized (lockA) {
System.out.println(Thread.currentThread().getName() + "------------lockA(lockB)==>have lockA into lockA");
synchronized (lockB) {
System.out.println(Thread.currentThread().getName() + "------------lockA(lockB)==>have lockB into lockB");
}
}
synchronized (lockB) {
System.out.println(Thread.currentThread().getName() + "------------lockB(lockA)==>have lockB into lockB");
synchronized (lockA) {
System.out.println(Thread.currentThread().getName() + "------------lockB(lockA)==>have lockA into lockA");
}
}
}
}
}
// 测试类
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(2);
MyRunnable mr1 = new MyRunnable();
threadPool.submit(mr1);
MyRunnable mr2 = new MyRunnable();
threadPool.submit(mr2);
}
}
运行结果:
pool-1-thread-2------------lockA(lockB)==>have lockA into lockA
pool-1-thread-2------------lockA(lockB)==>have lockB into lockB
pool-1-thread-2------------lockB(lockA)==>have lockB into lockB
pool-1-thread-1------------lockA(lockB)==>have lockA into lockA
二、线程状态(等待与唤醒)
案例:生产者与消费者
// 基础类
public class Milk {
private boolean hasMilk = false;
public Milk() {
}
public boolean isHasMilk() {
return hasMilk;
}
public void setHasMilk(boolean hasMilk) {
this.hasMilk = hasMilk;
}
}
// 生产者
public class Provider implements Runnable {
@Override
public void run() {
// 增加循环,让Provider一直生产牛奶
while (true) {
synchronized (Test.milk) {
// 判断是否有牛奶
if (Test.milk.isHasMilk() == true) { // 有牛奶,Provider进入等待状态,等待Consumer消费牛奶
try {
Test.milk.wait(); // Provider进入等待状态,归还milk锁,Consumer获取到锁,执行同步代码块代码
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 没有牛奶,生产牛奶
System.out.println("Provider生产牛奶(需要3秒)");
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 3秒后,修改牛奶状态,并唤醒Consumer消费牛奶
Test.milk.setHasMilk(true);
Test.milk.notify();
System.out.println("Provider生产完毕牛奶,Consumer快来消费牛奶吧");
}
}
}
}
// 消费者
public class Consumer implements Runnable {
@Override
public void run() {
// 增加循环,让Consumer一直消费牛奶
while (true) {
synchronized (Test.milk) {
// 判断奶瓶是否有牛奶
if (Test.milk.isHasMilk() == false) { // 没有,Consumer进入等待状态,等待Provider生产奶
try {
Test.milk.wait(); // Consumer进入等待,归还锁,Provider会获取锁,生产牛奶
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 奶瓶有牛奶,Consumer消费牛奶
System.out.println("Consumer消费牛奶(需要3秒)");
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 生产完毕,修改牛奶状态,唤醒Provider生产牛奶
Test.milk.setHasMilk(false);
Test.milk.notify();
System.out.println("Consumer消费完毕牛奶,Provider快来生产牛奶");
}
}
}
}
// 测试类
public class Test {
// 同步锁,保证唯一
public static Milk milk = new Milk();
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(2);
threadPool.submit(new Provider());
threadPool.submit(new Consumer());
}
}