生产者与消费者模式
关键技术点:
找到生产者和消费者之间的核心纽带,放入synchronized中保证在notify和wait的时候是通知到同一个对象下的同步代码块
案例:要求生产者生产两种商品,每次将玩具卖完后生产者会继续生产
案例分析:
生产者:
消费者
测试Demo
public class Threadtest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Toy t=new Toy();
GetThread t1 = new GetThread(t);
SetThread t2 = new SetThread(t);
t1.start();
t2.start();
}
}
玩具toy
public class Toy {
private String name;
private int num;
private boolean flag;
public Toy() {
super();
}
public Toy(String name, int num, boolean flag) {
super();
this.name = name;
this.num = num;
this.flag = flag;
}
@Override
public String toString() {
return "Toy [name=" + name + ", num=" + num + ", flag=" + flag + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
消费者
//消费者
public class GetThread extends Thread {
Toy t;
public GetThread(Toy t) {
super();
this.t = t;
}
@Override
public void run() {
// TODO Auto-generated method stub
{
while(true){
synchronized(t){
if(t.isFlag()){//有玩具
int newnum=t.getNum()-1;
t.setNum(newnum);
System.out.println(t.getName()+"还剩"+newnum);
if(t.getNum()<=0)
{
t.notify();
t.setFlag(false);
}
}else{
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}}
}
}
}
生产者
//生产者模型
public class SetThread extends Thread {
Toy t;
public SetThread(Toy t) {
super();
this.t = t;
}
@Override
public void run() {
int i=1;
while(true){
synchronized(t){
if(!t.isFlag())//没有玩具
{
if(i%2==0){
t.setName("阿狸");
t.setNum(5);
}else{
t.setName("海绵宝宝");
t.setNum(6);
}
t.setFlag(true);
t.notify();
}
else
{
try {
i++;
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
例题
/*
*作业7:Java --写两个线程,一个线程打印1-52,另一个线程打印字母A-Z。打印 顺序为12A34B56C……5152Z (等待唤醒机制)
编写程序实现,子线程循环10次,接着主线程循环20次,接着再子线程循环10次,主线程循环20次,如此反复,循环50次.
*/
注解:我采用的是生产消费模型, 该模型要核心纽带(numandword-》nw类)其中有数字的flag字母的flag 对象的目的是用来做两个类之间的锁对象
//因为notify只能通知等待池中同一对象对应的wait线程
public class F_15 {
/*
* 作业7:Java --写两个线程,一个线程打印1-52,另一个线程打印字母A-Z。打印 顺序为12A34B56C……5152Z (等待唤醒机制)
编写程序实现,子线程循环10次,接着主线程循环20次,接着再子线程循环10次,主线程循环20次,如此反复,循环50次.
*/
//我采用的是生产消费模型, 该模型要核心纽带(numandword-》nw类)其中有数字的flag字母的flag 对象的目的是用来做两个类之间的锁对象
//因为notify只能通知等待池中同一对象对应的wait线程
public static void main(String[] args) {
// TODO Auto-generated method stub
NW n=new NW(true,false);
new N1(n).start();;
new N2(n).start();;
}
}
enum Locks{LOCK}
class N2 extends Thread{
NW n;
static int i=1;
public N2(NW n) {
super();
this.n = n;
}
public void run() {
while(i<53){
synchronized(n){
if(!n.getFlag2()){//数字键关闭
try {
n.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{//数字打印
System.out.println(i+" "+(i+1));
i+=2;
n.setFlag2(false);
n.setFlag1(true);
n.notify();
}
}
}
}
}
class N1 extends Thread{
NW n;
static char ch='A';
public N1(NW n) {
super();
this.n = n;
}
public void run() {
while(ch<='Z'){
synchronized(n){
if(!n.getFlag1()){//字符键关闭
try {
n.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
System.out.println(ch);
ch++;
n.setFlag1(false);
n.setFlag2(true);
n.notify();
}
}
}
}
}
class NW{
private Boolean flag1;//num
private Boolean flag2;//char
public NW(Boolean flag1, Boolean flag2) {
super();
this.flag1 = flag1;
this.flag2 = flag2;
}
public Boolean getFlag1() {
return flag1;
}
public void setFlag1(Boolean flag1) {
this.flag1 = flag1;
}
public Boolean getFlag2() {
return flag2;
}
public void setFlag2(Boolean flag2) {
this.flag2 = flag2;
}
}