线程间通信(等待,唤醒)&Java中sleep()和wait()比较

1.什么是线程间通信?

  多个线程在处理同一资源,但是任务却不同

生活中栗子:有一堆煤,有2辆车往里面送煤,有2辆车往外拉煤,这个煤就是同一资源,送煤和拉煤就是任务不同。

 2.等待/唤醒机制。

  涉及的方法:

  (1)wait(): 让线程处于冻结状态,被wait的线程会被存储到线程池(容器)中
  (2)notify():唤醒线程池中一个线程(任意).
  (3)notifyAll():唤醒线程池中的所有线程。

  这些方法都必须定义在同步中
  因为这些方法是用于操作线程状态的方法。
  必须要明确到底操作的是哪个锁上的线程。

  什么是线程池?

  顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程而不用自行创建,使用完毕后不需要销毁放入池中,从而减少创建和销毁对象的开销。


  为什么操作线程的方法wait notify notifyAll定义在了Object类中

  因为这些方法是监视器的方法。监视器其实就是锁,就是栗子中的r
  锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。

栗子:(谁拿锁谁执行) 

class Resource
{
	private String name;
	private String sex;
	private boolean flag = false;

	public synchronized void set(String name,String sex)
	{
		if(flag)//为真的时候,就直接进入wait,这样该线程就释放了执行权了。为假就执行下面的语句
			try{this.wait();}catch(InterruptedException e){}
		this.name = name;
		this.sex = sex;
		flag = true;
		this.notify();//唤醒输出线程,输出线程具备了执行资格。抢来了CPU执行权
	}

	public synchronized void out()
	{
		if(!flag)
			try{this.wait();}catch(InterruptedException e){}
		System.out.println(name+"...+...."+sex);
		flag = false;
		notify();//唤醒输入线程
	}
}

//输入
class Input implements Runnable
{
	Resource r ;
//	Object obj = new Object();
	Input(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		int x = 0;
		while(true)
		{
			if(x==0)
			{
				r.set("mike","nan");
			}
			else
			{
				r.set("丽丽","女女女女女女");
			}
			x = (x+1)%2;
		}
	}
}
//输出
class Output implements Runnable
{

	Resource r;
//	Object obj = new Object();
	Output(Resource r)
	{
		this.r = r;
	}

	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}

class  ResourceDemo3
{
	public static void main(String[] args) 
	{
		//创建资源。
		Resource r = new Resource();
		//创建任务。
		Input in = new Input(r);
		Output out = new Output(r);
		//创建线程,执行路径。
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		//开启线程
		t1.start();
		t2.start();
	}
}

3.sleep()和wait()比较

 (1)对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。

 (2)sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态。

 (3)在调用sleep()方法的过程中,线程不会释放对象锁。

  而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。

 (4)wait可以指定时间也可以不指定时间,sleep必须指定时间

 (5)在同步中时,对cpu的执行权和锁的处理不同。
  wait:释放执行权,释放锁
  sleep:释放执行权,不释放锁

栗子:

  关于sleep和wait,以下描述错误的是D

   A.sleep是线程类的方法,wait是object的方法

   B.sleep不释放对象锁,wait放弃对象锁

   C.sleep暂停线程,但监控状态依然保持,结束后会自动恢复

   D.wait进入等待锁定池,只有针对此对象发出notify方法获得对象锁进入运行状态

原因:是D中,准备获取对象锁进入运行状态,而不是立即进入

4.线程状态

原文地址:https://www.cnblogs.com/GumpYan/p/5744459.html