八股必会内容
生产者消费者
Synchronized 版本
重点是一定要用while来判断,否则会出现虚假唤醒(那什么虚假唤醒呢,虚假唤醒就是由于把所有线程都唤醒了,但是只有其中一部分是有用的唤醒操作,其余的唤醒都是无用功,对于不应该被唤醒的线程而言,便是虚假唤醒。)
对于这个例子中,假设A完成了+1的任务,那么会notifyAll(),而C也是+1的线程,应当继续去wait,如果是if的话直接继续执行+1就出问题了。因此应当用while,当不该被唤醒是自己继续去睡。
package com.ldl.test;
//-Xms10m -Xms10m -XX:+PrintGCDetails
public class Main{
public static void main(String[] args) throws Exception {
// Main main = new Main();
Data data = new Data();
new Thread(()->{ try { for (int i = 0; i < 10; i++) data.increasement(); } catch (InterruptedException e) { e.printStackTrace(); } },"A").start();
new Thread(()->{ try { for (int i = 0; i < 10; i++) data.decreasement(); } catch (InterruptedException e) { e.printStackTrace(); } },"B").start();
new Thread(()->{ try { for (int i = 0; i < 10; i++) data.increasement(); } catch (InterruptedException e) { e.printStackTrace(); } },"C").start();
new Thread(()->{ try { for (int i = 0; i < 10; i++) data.decreasement(); } catch (InterruptedException e) { e.printStackTrace(); } },"D").start();
}
}
class Data{
private int num =0;
public synchronized void increasement() throws InterruptedException {
while (num!=0){ //num为0的时候才去操作
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName()+"=>"+num);
this.notifyAll();
}
public synchronized void decreasement() throws InterruptedException {
while(num==0){//num不为0的时候才去操作
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName()+"=>"+num);
this.notifyAll();
}
}
Lock版本
流程: 判断等待、业务、通知
不指定下一个线程
package com.ldl.test;
//-Xms10m -Xms10m -XX:+PrintGCDetails
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
public static void main(String[] args) throws Exception {
// Main main = new Main();
Data data = new Data();
new Thread(() -> { try { for (int i = 0; i < 10; i++) data.increasement(); } catch (InterruptedException e) { e.printStackTrace(); } }, "A").start();
new Thread(() -> { try { for (int i = 0; i < 10; i++) data.decreasement(); } catch (InterruptedException e) { e.printStackTrace(); } }, "B").start();
new Thread(() -> { try { for (int i = 0; i < 10; i++) data.increasement(); } catch (InterruptedException e) { e.printStackTrace(); } }, "C").start();
new Thread(() -> { try { for (int i = 0; i < 10; i++) data.decreasement(); } catch (InterruptedException e) { e.printStackTrace(); } }, "D").start();
}
}
class Data {
private int num = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void increasement() throws InterruptedException {
lock.lock();
try {
while (num != 0) { //num为0的时候才去操作
condition.await();
}
num++;
System.out.println(Thread.currentThread().getName() + "=>" + num);
condition.signalAll();
} finally {
lock.unlock();
}
}
public synchronized void decreasement() throws InterruptedException {
lock.lock();
try {
while (num == 0) {//num不为0的时候才去操作
condition.await();
}
num--;
System.out.println(Thread.currentThread().getName() + "=>" + num);
condition.signalAll();
} finally {
lock.unlock();
}
}
}
指定下一个线程
- 需要一个标志位去记录应该到哪个执行了
- 需要Condition唤醒对应的线程
package com.ldl.test;
//-Xms10m -Xms10m -XX:+PrintGCDetails
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
public static void main(String[] args) throws Exception {
// Main main = new Main();
Data data = new Data();
new Thread(() -> { try { for (int i = 0; i < 10; i++) data.printA(); } catch (InterruptedException e) { e.printStackTrace(); } }, "A").start();
new Thread(() -> { try { for (int i = 0; i < 10; i++) data.printB(); } catch (InterruptedException e) { e.printStackTrace(); } }, "B").start();
new Thread(() -> { try { for (int i = 0; i < 10; i++) data.printC(); } catch (InterruptedException e) { e.printStackTrace(); } }, "C").start();
}
}
class Data {
private int num = 1; //1A 2B 3C
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void printA() throws InterruptedException {
lock.lock();
try {
while (num!=1){
condition1.await();
}
System.out.println(Thread.currentThread().getName()+"AAAAA");
num=2;
condition2.signal();
} finally {
lock.unlock();
}
}
public void printB() throws InterruptedException {
lock.lock();
try {
while (num!=2){
condition2.await();
}
System.out.println(Thread.currentThread().getName()+"BBBBB");
num=3;
condition3.signal();
} finally {
lock.unlock();
}
}
public void printC() throws InterruptedException {
lock.lock();
try {
while (num!=3){
condition3.await();
}
System.out.println(Thread.currentThread().getName()+"CCCCC");
num=1;
condition1.signal();
} finally {
lock.unlock();
}
}
}
标签:八股,Thread,lock,InterruptedException,try,num,内容,必会,new
From: https://www.cnblogs.com/Liang2021/p/16855536.html