Java多线程生产者消费者
Java的多线程学习中,因为有练习的要求,扔个生产者消费者的代码放上来:
先解释一下,里面有三个类,分别是cook(厨师),waiter(服务生)和food,厨师生产食物,而服务生则端走食物。那么先写一个用锁去同步的多线程,代码其实很简单,就是厨师对食物进行更改,直接修改食物的类型(手撕鸡或者卤猪脚),就算是食物生产完成了。
public class TestThread {
public static void main(String[] args){
food f = new food();
cook c = new cook(f);
waiter w = new waiter(f);
Thread t1 = new Thread(c);
Thread t2 = new Thread(w);
t1.start();
t2.start();
}
}
class cook implements Runnable{
food f;
static final int count = 5;
cook(food f){
this.f = f;
}
@Override
public void run() {
for (int i = 0; i < count; i++) {
f.l.lock();
if(i % 2 == 0) {
f.setName("手撕鸡");
f.setTaste("麻辣味");
f.setFood();
}else{
f.setName("卤猪脚");
f.setTaste("卤煮味");
f.setFood();
}
f.l.unlock();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class waiter implements Runnable{
food f;
static final int count = 5;
waiter(food f){
this.f = f;
}
@Override
public void run() {
for (int i = 0; i < count; i++) {
f.l.lock();
f.getFood();
f.l.unlock();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class food{
String name;
String taste;
Lock l;
public food() {
l = new ReentrantLock();
}
public void setFood(){
System.out.println("厨师制作了" + taste + name);
}
public void getFood(){
System.out.println("服务员端走了" + taste + name);
}
public food(String name, String taste) {
this.name = name;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.taste = taste;
l = new ReentrantLock();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTaste() {
return taste;
}
public void setTaste(String taste) {
this.taste = taste;
}
}
那么这段代码运行的一个结果是这样的:
可以看到,我们虽然设置了线程同步(用的是显式锁),但是没规定是厨师先上菜还是服务员先端盘子,于是乎就出现了上图的服务员先端走了未初始化的food的情况。
鉴于课程的内容,这边就直接在food类中加一个信号量,用类似互斥锁的同步方法(其实生产者消费者问题,应该是厨师制作食物达到上限后,才沉睡,但是本问题是将一个食物反复操作,相当于上限只能是1),(厨师做完活以后就睡眠并唤醒服务员,服务员做完后也沉睡并唤醒厨师,原本是准备照着这么做的,结果我用的不是继承thread,而是继承Runnable接口,所以似乎不能这么用),那么用一个boolean信号量来做这个同步就好,代码和结果是这样的:
class cook implements Runnable{
food f;
static final int count = 50;
cook(food f){
this.f = f;
}
@Override
public void run() {
for (int i = 0; i < count; i++) {
if(!f.flag) {
f.l.lock();
if (i % 2 == 0) {
f.setName("手撕鸡");
f.setTaste("麻辣味");
f.setFood();
} else {
f.setName("卤猪脚");
f.setTaste("卤煮味");
f.setFood();
}
f.flag = true;
f.l.unlock();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class waiter implements Runnable{
food f;
static final int count = 50;
waiter(food f){
this.f = f;
}
@Override
public void run() {
for (int i = 0; i < count; i++) {
if(f.flag) {
f.l.lock();
f.getFood();
f.flag = false;
f.l.unlock();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
其中,在food类里加入了一个flag,这里觉得太长就不全放上来了,其实代码的修改不多。
这个时候运行的结果就比较舒适了:
这就是一个简单的生产者消费者线程同步练习。