一、Object 类对线程的支持
Object 类是所有类的父类,在此类中有以下集中方法是对线程操作有所支持的:
从表中我们可以发现,可以将一个线程设置为等待状态,但是对于唤醒的操作却有两个,分别为 notify() 和 notifyAll() 。一般来说,所有等待的线程按照顺序进行排列,如果现在使用了 notify() 方法,则会唤醒第 1 个等待的线程执行,而如果使用了 notifyAll() 方法,则会唤醒所有的等待线程,哪个线程的优先级高,哪个线程就有可能先执行。
二、加入等待与唤醒
如果想让生产者不重复生产,消费者不重复取走,则可以增加一个标志位,假设标志位为 Boolean 型变量,如果标志位的内容为 TRUE,则表示可以生产,但是不能取走,此时线程执行到了消费者则应该等待;如果标志位为 false,则表示可以取走,但是不能生产,如果生产者线程运行,则应该等待。
要实现以上功能,直接修改 Info 类即可,在 Info 类中加入标志位,并通过判断标志位完成等待与唤醒的操作:
class Info {
private String name = "JAVA";
private String content = "LANGUAGE";
private boolean flag = false;//设置标志位
public synchronized void set(String name,String content){//设置信息名称及内容
if(!flag){
try {
super.wait();//等待消费者取走
}catch (InterruptedException e){
e.printStackTrace();
}
}
this.setName(name);//设置信息名称
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
this.setContent(content);//设置信息内容
flag = false;//修改标志位,表示可以取走
super.notify();//唤醒等待线程
}
public synchronized void get(){//取得信息内容
if(flag){
try{
super.wait();//标志位 TRUE,不可以取走
}catch (InterruptedException e){
e.printStackTrace();
}
}
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(this.getName() + " --> " + this.getContent());//输出信息
flag = true;
super.notify();//唤醒等待线程
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getContent(){
return content;
}
public void setContent(String content){
this.content = content;
}
}
此时生产者每生产一个就要等待消费者去取走,消费者每取走一个就要等待生产者生产,这样就避免了重复生产和重复取走的问题。