编辑器:Notepad++;学习视频:毕向东Java基础教程
一、线程间的通信
(1)wait(),notify(),notifyAll(),用来操作线程,为什么定义在了Object类中?
- 这些方法存在于同步中
- 使用这些方法时,必须标识所属的同步的锁
- 锁可以是任意对象,任意对象调用的方法一定定义在Object类中
(2)wait()和sleep()有什么区别?
- wait():释放CPU执行权,释放锁
- sleep():释放CPU的执行权,不释放锁
(3)多个线程处理同一资源,但任务不同。
二、等待唤醒机制
(1)涉及的方法
- wait(): 使线程处于冻结状态,被wait()的线程会被存储到线程池中
- notify(): 唤醒线程池中的任意一个线程
- notifyAll(): 唤醒线程池中的所有线程
/*
*** 等待唤醒机制的基本示例 ***
多个线程操作同一资源,任务不同,使用相同的锁
确保每输入一项,就相应的输出一项
*/
//定义资源
class Source1 //资源1,包含一些人的姓名和性别
{
String name;
String sex;
boolean flag = false; //一般都会定义标志位
}
//定义任务1,负责输入姓名和年龄
class Input1 implements Runnable
{
//为保证不同线程操作同一资源,这里不要实例化资源,而是以参数形式传递给构造函数
Source1 s;
Input1(Source1 s)
{
this.s = s;
}
//覆盖run方法
public void run()
{
int x = 0;
while(true)
{
synchronized(s) //保证不同线程使用的锁是惟一的
{
while(s.flag)
try{s.wait();}catch(InterruptedException e){} //每次唤醒都会判断flag,确定是否输入
//flag为true,则等待
//if(flag) //导致不该运行的线程运行了,产生数据输出错误
if(x==0)
{
s.name = "mike";
s.sex = "man";
System.out.println(Thread.currentThread().getName()+"...Input....name= "+s.name+"...Input...sex= "+s.sex);
}
else
{
s.name = "花花";
s.sex = "***famale***";
System.out.println(Thread.currentThread().getName()+"...Input....name= "+s.name+"...Input...sex= "+s.sex);
}
x = (x+1)%2; //0,1切换机制
s.flag = true;
//s.notify(); //while+notify,会出现死锁:所有线程处于等待状态
s.notifyAll();
}
}
}
}
//定义任务2,负责输出姓名和年龄
class Output1 implements Runnable
{
Source1 s;
Output1(Source1 s)
{
this.s = s;
}
public void run()
{
while(true)
{
synchronized(s)
{
while(!s.flag)
try{s.wait();}catch(InterruptedException e){} //每次唤醒都会判断flag,确定是否输出
System.out.println(Thread.currentThread().getName()+"...Output...name= "+s.name+"...Output..sex= "+s.sex);
System.out.println();
s.flag = false;
s.notifyAll();
}
}
}
}
class WaitNotifyDemo
{
public static void main(String[] args)
{
//创建资源
Source1 s = new Source1();
//创建任务
Input1 in = new Input1(s);
Output1 out = new Output1(s);
//创建线程
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
//开启线程
t1.start();
t2.start();
}
}