一开始我选用的是自己当时较为顺手的实现Runnable的做法来做这道题,利用继承来获取共享数据,结果陷入死锁,百思不得其解。反复审阅代码发现,这样做,生产者和消费者类始终共用的同一共同数据,造成死锁。
package Java2;
class barn {
static int product = 0;
}
class Productor extends barn implements Runnable {
@Override
public void run() {
synchronized (this) {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (product < 20) {
product++;
System.out.println(Thread.currentThread().getName() + "生产了第" + product + "件商品");
notify();
} else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class Customer extends barn implements Runnable {
@Override
public void run() {
synchronized (this) {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (product > 0) {
System.out.println(Thread.currentThread().getName() + "消费了第" + product + "件商品");
product--;
notify();
} else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public class Classic {
public static void main(String[] args) {
Productor p = new Productor();
Customer cu = new Customer();
Thread x = new Thread(p);x.setName("生产者:");
Thread y = new Thread(cu);y.setName("消费者:");
x.start();
y.start();
}
}
最后,使用了同步方法+继承Thread来解这道题。将具体功能都封装成同步方法,然后让消费者和生产者类来实例化并调用(implements Runnable貌似不支持类中再去带参构造所以才换的继承Thread)。
package Java2;
class Barn {
private int product = 0;
public synchronized void produceProduct() {
if (product < 20) {
product++;
System.out.println(Thread.currentThread().getName() + "生产了第" + product + "件商品");
notify();
} else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void consumeProduct() {
if (product > 0) {
System.out.println(Thread.currentThread().getName() + "消费了第" + product + "件商品");
product--;
notify();
} else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Productor extends Thread{
private Barn barn;
public Productor(Barn barn) {
this.barn = barn;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
barn.produceProduct();
}
}
}
class Customer extends Thread {
private Barn barn;
Customer(Barn barn){
this.barn = barn;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
barn.consumeProduct();
}
}
}
public class Classic {
public static void main(String[] args) {
Barn b = new Barn();
Productor p = new Productor(b); p.setName("生产者:");
Customer cu = new Customer(b); cu.setName("消费者:");
p.start();
cu.start();
}
}
小结:在多线程当中,确定好共享数据真的非常重要。如果没有给线程分工明确地去调用共享数据,一不留神就会造成死锁。