栗子:
实现目标:
生产者/消费者问题
此题目需实现一个生产者,店员,消费者之前程序.生产者生产产品,生产好之后交给店员,店员只能持有固定数量的产品,店员与生产者之间保持信息交流,即店员持有的产品数量小于所需持有的固定数量时,生产者开始生产产品至固定数量而后停止生产;消费者与店员之间也保持信息交流,消费者每消费一个产品,店员持有的产品数量减少相应的数目,如此往复循环
分析问题:
1.是否是多线程? 是,生产者线程,消费者线程
2.是否存在线程安全问题(是否共享数据)? 是,店员或产品
3.如何解决线程安全问题/ 同步机制,三种方法
4.是否设计线程通信? 是
代码实现:
首先利用面向对象的设计思想,因为店员与生产者及消费者都有交流,不妨将店员设为两者沟通的桥梁,设置一个Cleck类,在该类中分别声明生产产品和消费产品的方法
class Clerk{
private int producount = 0; //设置初始产品数量为0
//生产产品
//声明生产产品的方法,使用synchronized同步方法的方式解决线程安全问题
public synchronized void produceProduct(){
if (producount < 20){ //判断店员持有的产品数量是否超过20,若小于则生产产品
producount ++;
System.out.println(Thread.currentThread().getName()+",开始生产第"+producount+"个产品");
notify(); //调用notify()方法唤醒阻塞的线程
}else{
//等待
try {
wait(); //产品数量超过20时,调用wait()方法,使线程进入阻塞状态,等待消费者消费产品,从而实现线程间的通信问题,此时需使用try{ }catch{ }语句,处理异常
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//消费产品
//声明消费产品的方法,使用synchronized同步方法的方式解决线程安全问题
public synchronized void ConsumeProduct(){
if (producount > 0){ //判断店员持有的产品数量是否大于0,若大于则可以消费产品
System.out.println(Thread.currentThread().getName()+",开始消费第" +producount+"个产品");
producount--;
notify(); //调用notify()方法唤醒阻塞的线程
}else{
//等待
try {
wait(); //产品数量小于等于0时,调用wait()方法,使线程进入阻塞状态,等待生产者生产产品,从而实现线程间的通信问题,此时需使用try{ }catch{ }语句,处理异常
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
再分别声明生产者类和消费者类
class producer extends Thread{ //声明生产者类,继承Thread
private Clerk clerk;
public producer(Clerk clerk){
this.clerk=clerk;
}
@Override
public void run() {
System.out.println(getName() + ":开始生产...");
while (true){
try {
Thread.sleep(5); //调用sleep()方法,控制线程等待的时间,此时使用try{ }catch{ }语句,处理异常
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.produceProduct(); //调用clerk类中生产产品的方法
}
}
}
class consume extends Thread{ //声明消费者类,继承Thread
private Clerk clerk;
public consume(Clerk clerk){
this.clerk=clerk;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(10); //调用sleep()方法,控制线程等待的时间,此时使用try{ }catch{ }语句,处理异常
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.ConsumeProduct(); //调用clerk类中消费产品的方法
}
}
}
最后在main方法中创建线程对象及调用开始方法,使线程运行
public class ProductTest {
public static void main(String[] args) {
Clerk clerk = new Clerk(); //创建Clerk类的对象
producer p1 = new producer(clerk); //将创建的clerk对象赋给producer方法,并创建producer对象
p1.setName("生产者1");
consume c1 = new consume(clerk); //将创建的clerk对象赋给consume方法,并创建consume对象
c1.setName("消费者1");
consume c2 = new consume(clerk);
c2.setName("消费者2");
p1.start(); //调用start()方法,使线程开始执行
c1.start();
c2.start();
}
}