zoukankan      html  css  js  c++  java
  • 多线程间的通讯之等待唤醒机制

    线程间的通讯:
    事实上就是多个线程在操作同一个资源。
    可是操作动作不同

    样例:

    需求:模拟简单卖票系统(输入一个人。紧接着输出一个人)

    class Res
    {
    	String name;
    	String sex;
    }
    class Input  implements Runnable
    {
    	private Res r;
    	private int t=0;
    	Input(Res r)
    	{
    		this.r=r;
    	}
    	public void run()
    	{
    		while(true)
    		{
    			if(t==1)
    			{
    				r.name="nike";
    				r.sex="man";
    			}
    			else 
    			{
    				r.name="丽丽";
    				r.sex="女女";
    			}
    			t=(t+1)%2;
    		}
    	}
    }
    class Output  implements Runnable
    {
    	private Res r;
    	Output(Res r)
    	{
    		this.r=r;
    	}
    	public void run()
    	{
    		while(true)
    		{
    			System.out.println("output....."+r.name+"+++"+r.sex);
    		}
    	}
    }
    class InputOutputDemo
    {
    	public static void main(String[] args)
    	{
    		Res r=new Res();
    		Input in=new Input(r);
    		Output out=new Output(r);
    		Thread t1=new Thread(in);
    		Thread t2=new Thread(out);
    		t1.start();
    		t2.start();
    	}
    }

    出现了安全问题(输出了丽丽  MAN)

    同步后

    class Res
    {
    	String name;
    	String sex;
    }
    class Input  implements Runnable
    {
    	private Res r;
    	private int t=0;
    	Input(Res r)
    	{
    		this.r=r;
    	}
    	public void run()
    	{
    		while(true)
    		{
    			synchronized(Res.class)
    			{
    				if(t==1)
    				{
    					r.name="nike";
    					r.sex="man";
    				}
    				else 
    				{
    					r.name="丽丽";
    					r.sex="女女";
    				}
    				t=(t+1)%2;
    			}
    		}
    	}
    }
    class Output  implements Runnable
    {
    	private Res r;
    	Output(Res r)
    	{
    		this.r=r;
    	}
    	public void run()
    	{
    		while(true)
    		{
    			synchronized(Res.class)
    			{
    				System.out.println("output....."+r.name+"+++"+r.sex);
    			}
    		}
    	}
    }
    class InputOutputDemo2
    {
    	public static void main(String[] args)
    	{
    		Res r=new Res();
    		Input in=new Input(r);
    		Output out=new Output(r);
    		Thread t1=new Thread(in);
    		Thread t2=new Thread(out);
    		t1.start();
    		t2.start();
    	}
    }


    尽管安全 问题攻克了,但并没出现我们想要的一男一女交替的情景

    这是就引进一种方法:等待唤醒机制

    class Res
    {
    	String name;
    	String sex;
    	boolean flag;
    }
    class Input  implements Runnable
    {
    	private Res r;
    	private int t=0;
    	Input(Res r)
    	{
    		this.r=r;
    	}
    	public void run()
    	{
    		while(true)
    		{
    			synchronized(r)
    			{
    				if(r.flag)
    					try{r.wait();}catch(Exception e){}
    				if(t==1)
    				{
    					r.name="nike";
    					r.sex="man";
    				}
    				else 
    				{
    					r.name="丽丽";
    					r.sex="女女";
    				}
    				t=(t+1)%2;
    				r.flag=true;
    				r.notify();
    			}
    		}
    	}
    }
    class Output  implements Runnable
    {
    	private Res r;
    	Output(Res r)
    	{
    		this.r=r;
    	}
    	public void run()
    	{
    		while(true)
    		{
    			synchronized(r)
    			{
    				if(!r.flag)
    					try{r.wait();}catch(Exception e){}
    				System.out.println("output....."+r.name+"+++"+r.sex);
    				r.flag=false;
    				r.notify();
    			}
    		}
    	}
    }
    class InputOutputDemo3
    {
    	public static void main(String[] args)
    	{
    		Res r=new Res();
    		Input in=new Input(r);
    		Output out=new Output(r);
    		Thread t1=new Thread(in);
    		Thread t2=new Thread(out);
    		t1.start();
    		t2.start();
    	}
    }


     

    wait:
    notify();
    notifyAll();

    都使用在同步中,由于要对持有监视器(锁)的操作。
    所以要使用在同步中,由于仅仅有同步才具有锁。

    为什么这些操作线程的凤飞飞要定义Object类中呢?
    由于这些方法在操作同步中线程时。都必需要标识它们所操作线程中的锁,
    仅仅有同一个锁上的被等待线程。能够被同一个锁上notify唤醒。
    不能够被不同锁中的线程进行唤醒。

    也就是说,等待和唤醒必须是同一个锁。


    而锁能够是随意对象,所以能够被随意对象调用的方法定义Object类中。

    以下进行代码改良:

    class Res
    {
    	private String name;
    	private String sex;
    	private boolean flag;
    	public synchronized void  set(String name,String sex)
    	{
    		if(this.flag)
    		  try{this.wait();}catch(Exception e){}
    
    		this.name=name;
    		this.sex=sex;
    
    		this.flag=true;
    		  this.notify();
    
    	}
    	public synchronized void out()
    	{
    		if(!this.flag)
    		 try{this.wait();}catch(Exception e){}
    		System.out.println("output....."+this.name+"+++"+this.sex);
    		this.flag=false;
    				this.notify();
    	}
    }
    class Input  implements Runnable
    {
    	private Res r;
    	private int t=0;
    	Input(Res r)
    	{
    		this.r=r;
    	}
    	public void run()
    	{
    		while(true)
    		{
    			synchronized(r)
    			{
    				if(t==1)
    					r.set("nike","man");
    				else 
    					r.set("丽丽","女女女");
    				t=(t+1)%2;
    			}
    		}
    	}
    }
    class Output  implements Runnable
    {
    	private Res r;
    	Output(Res r)
    	{
    		this.r=r;
    	}
    	public void run()
    	{
    		while(true)
    		{
    			synchronized(r)
    			{
    				r.out();
    			}
    		}
    	}
    }
    class InputOutputDemo4
    {
    	public static void main(String[] args)
    	{
    		Res r=new Res();
    		new Thread(new Input(r)).start();
    		new Thread(new Output(r)).start();
    		/*
    		Input in=new Input(r);
    		Output out=new Output(r);
    		Thread t1=new Thread(in);
    		Thread t2=new Thread(out);
    		t1.start();
    		t2.start();
    		*/
    	}
    }


     


     

  • 相关阅读:
    网络相关命令
    jmeter压力测试接口
    mysql+mycat+centos7
    centos7开放端口
    mysql主从库配置文件
    读写分离
    Memcached与Redis的区别和选择
    mybatis 学习
    redis 轻松入门
    swagger 框架使用
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7375029.html
Copyright © 2011-2022 走看看