生产者消费者模型应该都很熟悉了,作为一个重要的基础知识,一般“操作系统”课里会让实现。这里我让生产者和消费者交替出现(因为当年面试字节跳动的时候面试官让写个多线程轮流打印Hello与World)
这里的共享资源是装着Apple的一个List,每个Apple有自己的id便于打印,这里用的Synchronized代码块,锁定的是list,所以要用list.wait,list.notify,如果锁定的this或者用同步方法,就用wait和notify就行了。因为wait和notify是某个对象的方法。
package multi_thread;
import java.util.ArrayList;
/*
* 生产者消费者多线程 模型
*/
class Apple {
int id;
public Apple(int id) {
// TODO Auto-generated constructor stub
this.id = id;
}
}
class Consumer implements Runnable {
public ArrayList<Apple> list;
public Consumer(ArrayList<Apple> list) {
this.list = list;
}
public void consume() {
for (int i = 0; i < 10; i++) {
synchronized (list) {
while(list.isEmpty()) {
try {
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Apple temp = list.get(list.size() - 1);
System.out.println("消费" + temp.id);
list.remove(list.size()-1);
list.notify();
if(i!=9) //当i是9的时候就不要wait了,让程序结束吧
try {
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
@Override
public void run() {
// TODO Auto-generated method stub
consume();
}
}
class Producer implements Runnable {
public ArrayList<Apple> list;
public Producer(ArrayList<Apple> list) {
this.list = list;
}
public void produce() {
for (int i = 0; i < 10; i++) {
synchronized (list) {
while(list.size()>=10) {
try {
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Apple temp = new Apple(i);
System.out.println("生产"+temp.id);
list.add(temp);
list.notify();
try {
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
@Override
public void run() {
// TODO Auto-generated method stub
produce();
}
}
public class MulThread {
public static void main(String[] args) {
ArrayList<Apple> list = new ArrayList<>();
Runnable consumer = new Consumer(list);
Runnable producer = new Producer(list);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
t1.start();
t2.start();
}
}
结果是:
生产0
消费0
生产1
消费1
生产2
消费2
生产3
消费3
生产4
消费4
生产5
消费5
生产6
消费6
生产7
消费7
生产8
消费8
生产9
消费9
用可重入公平锁方式:
import java.util.concurrent.locks.ReentrantLock;
public class FairLock implements Runnable {
public static ReentrantLock fairLock = new ReentrantLock(true);
@Override
public void run() {
while(true){
try{
fairLock.lock();
System.out.println(Thread.currentThread().getName());
}finally{
fairLock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread.currentThread().setPriority(10);
FairLock r1 = new FairLock();
Thread t1=new Thread(r1,"hello");
Thread t2=new Thread(r1,"world");
t1.start();t2.start();
return;
}
用ReentrantLock搭配Condition解决:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Thread_A implements Runnable {
Temp temp;
public Thread_A(Temp temp) {
// TODO Auto-generated constructor stub
this.temp = temp;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 5; i++)
temp.print_hello();
}
}
class Thread_B implements Runnable {
Temp temp;
public Thread_B(Temp temp) {
// TODO Auto-generated constructor stub
this.temp = temp;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 5; i++)
temp.print_world();
}
}
public class Temp {
private volatile boolean flag = true; // 记录打印 hello 还是 world 的标志
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void print_hello() {
try {
lock.lock();
while (flag == false)
condition.await();
System.out.println("hello");
flag = false;
condition.signal();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print_world() {
try {
lock.lock();
while (flag == true)
condition.await();
System.out.println("world");
flag = true;
condition.signal();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
Temp temp = new Temp();
new Thread(new Thread_A(temp)).start();
new Thread(new Thread_B(temp)).start();
}