一个JAVA多线程的实例
写出一组模拟生产者/消费者的协作程序
其中包括一个WoTou.java,代表消息
一个MsgQueue.java,为一个队列,提供put(Message msg)方法和get()方法
一个Produer.java,为生产者线程,在其run方法中每隔1秒产生一个Message对像并放入MsgQueue队列
一个Consumer.java为消费者线程,在其run方法中不断从MsgQueue队列中获取Message对像,并显示在屏幕上
一个TestMain.java,在其main方法中,启动2个Produer线程和2个消费者线程.
要求:
对于MsgQueue.java,队列的长度为10,当消息超过10个时,put()方法需要阻塞:当消息队列为空时,
get()方法需要阻塞。
public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p1= new Producer(ss,"p1");
Consumer c1= new Consumer(ss,"c1");
Producer p2= new Producer(ss,"p2");
Consumer c2= new Consumer(ss,"c2");
}
}
class WoTou<T> {
int id;
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou : " + id;
}
}
class SyncStack {
int index = 0;
WoTou[] arrWT = new WoTou[6];
public void push(WoTou wt) {
while(index == arrWT.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
arrWT[index] = wt;
index ++;
}
public WoTou pop() {
while(index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
index--;
return arrWT[index];
}
}
class Producer implements Runnable {
SyncStack ss = null;
String a;
Producer(SyncStack ss,String a) {
this.ss = ss;
this.a= a;
Thread t=new Thread(this,a);
t.start();
}
public void run() {
for(int i=0; i<10; i++) {
synchronized(ss){
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println(a+" 生产了:" + wt);}
try {
Thread.sleep((int)(Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
SyncStack ss = null;
String a;
Thread t;
Consumer(SyncStack ss,String a) {
this.ss = ss;
this.a= a;
t=new Thread(this,a);
t.start();
}
public void run() {
for(int i=0; i<10; i++) {
synchronized(ss){
WoTou wt = ss.pop();
System.out.println(a+" 消费了: " + wt);}
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
p1 生产了:WoTou : 0
p2 生产了:WoTou : 0
p3 生产了:WoTou : 0
c1 消费了: WoTou : 0
c1 消费了: WoTou : 0
p3 生产了:WoTou : 1
c1 消费了: WoTou : 1
c1 消费了: WoTou : 0
p3 生产了:WoTou : 2
p1 生产了:WoTou : 1
c1 消费了: WoTou : 1
p2 生产了:WoTou : 1
p2 生产了:WoTou : 2
c1 消费了: WoTou : 2
p2 生产了:WoTou : 3
p3 生产了:WoTou : 3
c1 消费了: WoTou : 3
p3 生产了:WoTou : 4
p2 生产了:WoTou : 4
c1 消费了: WoTou : 4
c1 消费了: WoTou : 4
p1 生产了:WoTou : 2
c1 消费了: WoTou : 2
p2 生产了:WoTou : 5
p3 生产了:WoTou : 5
p2 生产了:WoTou : 6
栈里有6个
作为多线程交互一的一个重要应用,定义用户输入和输出的列队类或者堆栈类一定要看成一个整体放进同步语句块里面,不能简单的分别调用输入同步方法或者输出同步方法。下面的程序就有问题 下面这个是一个教程例子,但是结果不对。究其原因实际上是因为列队类或者堆栈类是一个可变类 ,这种可变类要是有参数传递给某些不可变类时,可变类的构造方法必须也设置成为同步方法,不然就会出错。
public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p = new Producer(ss);
Consumer c = new Consumer(ss);
new Thread(p).start();
new Thread(p).start();
new Thread(p).start();
new Thread(c).start();
}
}
class WoTou {
int id;
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou : " + id;
}
}
class SyncStack {
int index = 0;
WoTou[] arrWT = new WoTou[6];
public synchronized void push(WoTou wt) {
while(index == arrWT.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
arrWT[index] = wt;
index ++;
}
public synchronized WoTou pop() {
while(index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
index--;
return arrWT[index];
}
}
class Producer implements Runnable {
SyncStack ss = null;
Producer(SyncStack ss) {
this.ss = ss;
}
public void run() {
for(int i=0; i<20; i++) {
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("生产了:" + wt);
try {
Thread.sleep((int)(Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
SyncStack ss = null;
Consumer(SyncStack ss) {
this.ss = ss;
}
public void run() {
for(int i=0; i<20; i++) {
WoTou wt = ss.pop();
System.out.println("消费了: " + wt);
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行后的结果栈里有7个 为什么会这样呢?你思考一下