文章目录
1 使用wait、notify和synchronized实现生产者消费者
package org.example.pc;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class SafeQueue {
public static final int MAX_COUNT = 10;
List<String> queue = new CopyOnWriteArrayList<>();
public void put(String e) {
queue.add(e);
}
public String take() {
synchronized (queue) {
String element = queue.get(0);
queue.remove(element);
return element;
}
}
public int size() {
return queue.size();
}
}
package org.example.pc;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class Producer implements Runnable {
private SafeQueue safeQueue;
private String element;
public Producer(SafeQueue safeQueue, String element) {
this.safeQueue = safeQueue;
this.element = element;
}
@Override
public void run() {
// important, 一定要抢到safeQueue的前提下才能wait和notify
synchronized (safeQueue) {
if (safeQueue.MAX_COUNT - safeQueue.size() < 5) {
try {
safeQueue.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
for (int i = 0; i < 5; i++) {
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(3));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
safeQueue.put(element);
}
if (safeQueue.size() > 0) {
safeQueue.notify();
}
}
}
}
package org.example.pc;
public class Consumer implements Runnable {
private SafeQueue safeQueue;
public Consumer(SafeQueue safeQueue) {
this.safeQueue = safeQueue;
}
@Override
public void run() {
synchronized (safeQueue) {
while (true) {
if (safeQueue.size() == 0) {
try {
safeQueue.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
String element = safeQueue.take();
System.out.println(element);
if (safeQueue.size() < SafeQueue.MAX_COUNT) {
safeQueue.notify();
}
}
}
}
}
package org.example.pc;
public class Client {
public static void main(String[] args) {
SafeQueue safeQueue = new SafeQueue();
for (int i = 0; i < 4; i++) {
new Thread(new Producer(safeQueue, String.valueOf(i))).start();
}
for (int i = 0; i < 1; i++) {
new Thread(new Consumer(safeQueue)).start();
}
}
}
2 ABC三个线程分别打印ABC,现实现能够循环N次打印ABC
V2.0 使用wait()和notifyAll()
2.1 优缺点
进程可以终止。
便于理解和实现。
2.2 代码
package org.example;
public class SkMain {
public static void main(String[] args) {
ABCPrinter printer = new ABCPrinter();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
printer.printA();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
printer.printB();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
printer.printC();
}
}
}).start();
}
}
class ABCPrinter {
private volatile int value = 1;
public void printA() {
synchronized (this) {
while(value != 1) {
try {
wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("A");
value++;
notifyAll();
}
}
public void printB() {
synchronized (this) {
while(value != 2) {
try {
wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("B");
value++;
notifyAll();
}
}
public void printC() {
synchronized (this) {
while(value != 3) {
try {
wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("C");
value = 1;
notifyAll();
}
}
}
Reference
https://blog.csdn.net/realYuzhou/article/details/108367264
V1.0 面试挂的比较low的版本,只使用synchronized
1.1 缺点
程序不会终止
1.2 代码
A.java
package org.example;
public class A implements Runnable {
private B b;
private C c;
private int N = 5;
private boolean isFinish = false;
@Override
public void run() {
while (N > 0) {
synchronized (c) {
if (N ==5 && !isFinish) {
core();
} else if (c.isFinish() && !isFinish) { // wait c finish.
core();
}
}
}
}
private void core() {
isFinish = false;
System.out.println("A");
N--;
isFinish = true;
b.setFinish(false);
}
public void setFinish(boolean finish) {
isFinish = finish;
}
public boolean isFinish() {
return isFinish;
}
public void setC(C c) {
this.c = c;
}
public void setB(B b) {
this.b = b;
}
}
B.java
package org.example;
public class B implements Runnable {
A a;
C c;
private boolean isFinish = false;
@Override
public void run() {
while(true) {
synchronized (a) {
if (a.isFinish() && !isFinish) {
isFinish = false;
System.out.println("B");
isFinish = true;
c.setFinish(false);
}
}
}
}
public boolean isFinish() {
return isFinish;
}
public void setFinish(boolean finish) {
isFinish = finish;
}
public void setA(A a) {
this.a = a;
}
public void setC(C c) {
this.c = c;
}
}
C.java
package org.example;
public class C implements Runnable {
B b;
A a;
private boolean isFinish = false;
@Override
public void run() {
while (true) {
synchronized (b) {
if (b.isFinish() && !isFinish) {
isFinish = false;
System.out.println("C");
isFinish = true;
a.setFinish(false);
}
}
}
}
public boolean isFinish() {
return isFinish;
}
public void setFinish(boolean finish) {
isFinish = finish;
}
public void setB(B b) {
this.b = b;
}
public void setA(A a) {
this.a = a;
}
}
Main.java
package org.example;
public class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
C c = new C();
b.setA(a);
a.setB(b);
c.setB(b);
c.setA(a);
b.setC(c);
a.setC(c);
Thread threadA = new Thread(a);
Thread threadB = new Thread(b);
Thread threadC = new Thread(c);
threadA.start();
threadB.start();
threadC.start();
}
}