java--多线程通信

多线程间通信

总结以下通信方式:
wait():使当前线程处于等待状态,直到另一个线程调用notify(),notifyAll()方法为止。
notify():唤醒在同步监听器上处于等待状态的单个线程,如果有多个线程在等待,则任意唤醒一个线程。
notifyAll():唤醒在同步监听器上处于等待状态的所有线程。

wait():notify();notifyAll();
都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。

为什么这些操作线程的方法要定义Object类中呢?

因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁。只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。不可以对不同锁中的线程进行唤醒。

也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。

class Res
{
	String name;
	String sex;
	boolean flag = false;
}

class Input implements Runnable
{
	private Res r ;
	Input(Res r)
	{
		this.r = r;
	}
	public void run()
	{
		int x = 0;
		while(true)
		{
			synchronized(r)
			{

				if(r.flag)
					try{r.wait();}catch(Exception e){}
				if(x==0)
				{
					r.name="mike";
					r.sex="man";
				}
				else
				{
					r.name="丽丽";
					r.sex = "女女女女女";
				}
				x = (x+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(r.name+"...."+r.sex);
				r.flag = false;
				r.notify();
			}
		}
	}
}


class  Test
{
	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
{
	private String name;
	private String sex;
	private boolean flag = false;

	public synchronized void set(String name,String sex)
	{
		if(flag)
			try{this.wait();}catch(Exception e){}
		this.name = name;
		
		this.sex = sex;
		flag = true;
		this.notify();
	}
	public synchronized void out()
	{
		if(!flag)
			try{this.wait();}catch(Exception e){}
		System.out.println(name+"........"+sex);
		flag = false;
		this.notify();
	}
}

class Input implements Runnable
{
	private Res r ;
	Input(Res r)
	{
		this.r = r;
	}
	public void run()
	{
		int x = 0;
		while(true)
		{
			if(x==0)				
				r.set("mike","man");				
			else	
				r.set("丽丽","女女女女女");				
			x = (x+1)%2;
		}
	}
}

class Output implements Runnable
{
	private Res r ;
	
	Output(Res r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}


class  InputOutputDemo2
{
	public static void main(String[] args) 
	{
		Res r = new Res();

		new Thread(new Input(r)).start();
		new Thread(new Output(r)).start();
	}
另一个示例:

class Test 
{
	public static void main(String[] args) 
	{
		Resource r = new Resource();

		Producer pro = new Producer(r);
		Consumer con = new Consumer(r);

		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(pro);
		Thread t3 = new Thread(con);
		Thread t4 = new Thread(con);

		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}

class Resource
{
	private String name;
	private int count = 1;
	private boolean flag = false;
	public synchronized void set(String name)
	{
		while(flag)
			try{this.wait();}catch(Exception e){}
		this.name = name+"--"+count++;

		System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
		flag = true;
		this.notifyAll();
	}
	public synchronized void out()
	{
		while(!flag)
			try{wait();}catch(Exception e){}
		System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
		flag = false;
		this.notifyAll();
	}
}

class Producer implements Runnable
{
	private Resource res;

	Producer(Resource res)
	{
		this.res = res;
	}
	public void run()
	{
		while(true)
		{
			res.set("+商品+");
		}
	}
}

class Consumer implements Runnable
{
	private Resource res;

	Consumer(Resource res)
	{
		this.res = res;
	}
	public void run()
	{
		while(true)
		{
			res.out();
		}
	}
}
对于多个生产者和消费者。
·为什么要定义while判断标记。
原因:让被唤醒的线程再一次判断标记。
·为什么定义notifyAll,
因为需要唤醒对方线程。
因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。

如何停止线程?stop方法已经过时。

只有一种,run方法结束。
开启多线程运行,运行代码通常是循环结构。
只要控制住循环,就可以让run方法结束,也就是线程结束。

特殊情况:
当线程处于了冻结状态。
就不会读取到标记。那么线程就不会结束。

当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。
Thread类提供该方法 interrupt();

class StopThread implements Runnable
{
	private boolean flag =true;
	public synchronized void run()
	{
		while(flag)
		{
			try
			{wait();}
			catch(Exception e)
			{
				System.out.println(Thread.currentThread().getName()+"....Exception");
				flag=false;
			}
			System.out.println(Thread.currentThread().getName()+"....run");
		}
	}
	public void changeFlag()
	{
		flag = false;
	}
}
class  Test
{
	public static void main(String[] args) 
	{
		StopThread st = new StopThread();
		
		Thread t1 = new Thread(st);
		Thread t2 = new Thread(st);
		t1.start();
		t2.start(); 

		int num = 0;

		while(true)
		{
			if(num++ == 60)
			{
				//st.changeFlag();
				t1.interrupt();
				t2.interrupt();
				break;
			}
			System.out.println(Thread.currentThread().getName()+"......."+num);
		}
		System.out.println("over");
	}
}

setDaemon:将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
该方法必须在启动线程前调用。 

package Test;
class StopThread implements Runnable
{
	private boolean flag =true;
	public synchronized void run()
	{
		while(flag)
		{
			try
			{wait();}
			catch(Exception e)
			{
				System.out.println(Thread.currentThread().getName()+"....Exception");
				flag=false;
			}
			System.out.println(Thread.currentThread().getName()+"....run");
		}
	}
	public void changeFlag()
	{
		flag = false;
	}
}
class  Test
{
	public static void main(String[] args) 
	{
		StopThread st = new StopThread();
		
		Thread t1 = new Thread(st);
		Thread t2 = new Thread(st);

		t1.setDaemon(true);
		t2.setDaemon(true);
		t1.start();
		t2.start(); 

		int num = 0;

		while(true)
		{
			if(num++ == 60)
			{
				break;
			}
			System.out.println(Thread.currentThread().getName()+"......."+num);
		}
		System.out.println("over");
	}
}
join:
当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。
join可以用来临时加入线程执行。

class Demo implements Runnable
{
	public void run()
	{
		for(int x=0; x<30; x++)
		{
			System.out.println(Thread.currentThread().getName()+"....."+x);
		}
	}
}
class  Test
{
	public static void main(String[] args) throws Exception
	{
		Demo d = new Demo();
		Thread t1 = new Thread(d);
		Thread t2 = new Thread(d);
		t1.start();		
		t1.join();
		t2.start();
		for(int x=0; x<10; x++)
		{
			System.out.println("main....."+x);
		}
		System.out.println("over");
	}
}
yield:
暂停当前正在执行的线程对象,并执行其他线程。 减缓线程执行的频率。该方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。

class Demo implements Runnable
{
	public void run()
	{
		for(int x=0; x<30; x++)
		{
			System.out.println(Thread.currentThread().getName()+"....."+x);
			Thread.yield();
		}
	}
}
class  Test
{
	public static void main(String[] args) throws Exception
	{
		Demo d = new Demo();
		Thread t1 = new Thread(d);
		t1.start();		
		for(int x=0; x<10; x++)
		{
			System.out.println("main....."+x);
		}
		System.out.println("over");
	}
}


你可能感兴趣的:(java--多线程通信)