举例1:
class Info{ private String title; private String content; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } } class Productor implements Runnable{ private Info info; public Productor(Info info){ this.info=info; } @Override public void run() { for (int i=0;i<100;i++){ if (i%2==0){ this.info.setTitle("生产者"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.info.setContent(" 生产AAAAA"); }else{ this.info.setTitle("消费者"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.info.setContent(" 消费BBBBB"); } } } } class Customer implements Runnable{ private Info info; public Customer(Info info) { this.info = info; } @Override public void run() { for (int i=0;i<100;i++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.info.getTitle()+"-"+this.info.getContent()); } } } public class MyThread { public static void main(String[] args) { Info info=new Info(); new Thread(new Productor(info)).start(); new Thread(new Customer(info)).start(); } }以上代码产生两个问题:1、数据错位,发现不再是一个所需要的完整数据;
2、数据重复取出,数据重复设置。
下面解决第一个问题: 数据错位问题
数据错位完全是因为非同步的操作所造成的,应该使用同步处理。
class Info{ private String title; private String content; public synchronized void set(String title,String content) { this.title = title; try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } this.content = content; } public synchronized void get(){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.title+"-"+this.content); } } class Productor implements Runnable{ private Info info; public Productor(Info info){ this.info=info; } @Override public void run() { for (int i=0;i<100;i++){ if (i%2==0){ this.info.set("生产者"," 生产AAAAA"); }else{ this.info.set("消费者"," 消费BBBBB"); } } } } class Customer implements Runnable{ private Info info; public Customer(Info info) { this.info = info; } @Override public void run() { for (int i=0;i<100;i++){ this.info.get(); } } } public class MyThread { public static void main(String[] args) { Info info=new Info(); new Thread(new Productor(info)).start(); new Thread(new Customer(info)).start(); } }此时 数据的错位问题很好的得到了解决,但是重复操作问题更加严重了。
要想实现整个代码的操作,必须加入等待与唤醒机制。在Object类里面提供有专门的解决方法。
等待:
public final void wait() throws InterruptedException;
唤醒第一个等待线程:
public final void notify();
唤醒全部等待线程,哪个优先级高就先执行:
public final void notifyAll();
package thread; /** * Created by Saber on 2016/5/17. */ class Info{ private String title; private String content; private boolean flag=true; //flag=true,表示可以生产,但是不能取走; //flag=flase,表示可以取走,但是不可以生产; public synchronized void set(String title,String content) { //重复进入到了set()方法里面,发现不能够生产,所以要等待 if (flag==false){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.title = title; try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } this.content = content; this.flag=false; super.notify(); } public synchronized void get(){ if (flag==true){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.title+"-"+this.content); this.flag=true; super.notify(); } } class Productor implements Runnable{ private Info info; public Productor(Info info){ this.info=info; } @Override public void run() { for (int i=0;i<100;i++){ if (i%2==0){ this.info.set("生产者"," 生产AAAAA"); }else{ this.info.set("消费者"," 消费BBBBB"); } } } } class Customer implements Runnable{ private Info info; public Customer(Info info) { this.info = info; } @Override public void run() { for (int i=0;i<100;i++){ this.info.get(); } } } public class MyThread { public static void main(String[] args) { Info info=new Info(); new Thread(new Productor(info)).start(); new Thread(new Customer(info)).start(); } }以上操作会使得程序变慢;
请解释sleep()与wait()的区别
sleep()是Thread类定义的方法,wait()是Object类定义的方法;
sleep()可以设置休眠时间,时间一到自动唤醒,而wait()需要等待notify()进行唤醒。