Java 多线程 线程通信
线程通信 线程的等待与唤醒
多线程处理同一资源 各线程的任务不同 (对同一资源 有的线程使资源增加 有的线程使资源减少 不同线程应该通信 以便有效利用资源 )
举例
input线程 为资源的成员赋值
output线程 从资源的成员中获取值
两线程需默契配合好 ,input线程执行一次后 立即进入等待 唤醒对方output线程去执行, output线程执行一次后 立即进入等待 唤醒input线程去执行
注意 为防止IllegaMonitorStateEXception 无效的监视器状态异常 线程的等待与唤醒方法 必须是由锁对象(对象监视器)进行调用
/* * 定义资源类,有2个成员变量 * name,sex * 同时有2个线程,对资源中的变量操作 * 1个对name,age赋值 * 2个对name,age做变量的输出打印 */ public class Resource { public String name;//String类型的成员变量 new创建对象后 成员变量跟随对象进入堆 其默认值为null public String sex;// String类型的成员变量 new创建对象后 成员变量跟随对象进入堆 其默认值为null public boolean flag = false;//标记 初始为false 标示着资源尚未被赋值 Input线程可以赋值 Output线程进入等待 并去唤醒Input线程 }
/* * 输入的线程,对资源对象Resource中成员变量赋值 * 一次赋值 张三,男 * 下一次赋值 lisi,nv */ public class Input implements Runnable { /* Input线程 需要对资源r 进行成员变量赋值 * private Resource r = new Resource(); * 如果此处new出r对象 则该对象只是本线程自身所有 * 利用线程的构造方法 引入外部的r对象 才能最终保证 不同线程操作的是同一资源对象 */ private Resource r ; public Input(Resource r){ this.r = r; } public void run() { int i = 0 ; while(true){ //同步代码块使用的锁绝不能任意 要保证 Input线程与Output线程用同一把锁 //如果写成 synchronized(this) this是Input类的本类对象 Input线程用自己的同步锁 锁定资源 该锁与Output的锁不同 synchronized(r){ //标记是true,当前线程进入等待 if(r.flag){ try{r.wait();}catch(Exception ex){} } //标记为false 可以进行赋值 if(i%2==0){ r.name = "张三"; r.sex = "男"; }else{ r.name = "lisi"; r.sex = "nv"; } //已赋值结束 修改标记 r.flag = true;//标记被改为true 则即将被唤醒工作的 Output线程可以 去读取资源 r.notify();//唤醒 等待中的线程 } i++; } } }
/* * 输出线程,对资源对象Resource中成员变量,输出值 */ public class Output implements Runnable { /* Output线程 需要对资源r的成员值 进行输出打印 * 如果此处new出r对象 则该对象只是本线程自身所有 * 输出将是对象成员的默认值 null..null *private Resource r = new Resource(); *利用线程的构造方法 引入外部的r对象 才能最终保证 不同线程操作的是同一资源对象 */ private Resource r ;//私有成员 public Output(Resource r){ this.r = r; } public void run() { while(true){ //同步代码块使用的锁绝不能任意 要保证 Output线程与Input线程用同一把锁 //如果写成 synchronized(this) this是Output类的本类对象 Output线程用自己的同步锁 锁定资源 该锁与Input的锁不同 synchronized(r){ //判断标记,标记为false,资源还需要先被写入,当前的Output线程只能 等待wait() if(!r.flag){ try{r.wait();}catch(Exception ex){} } //标记true 则可以读取打印 System.out.println(r.name+".."+r.sex); //更改标记 r.flag = false;//标记改成false 已读取走 需要Input线程进行写入 r.notify();//唤醒等待中的线程 等待中的Input线程可以被唤醒notify() } } } }
/* * 开启输入线程和输出线程,实现赋值和打印值 */ public class ThreadDemo{ public static void main(String[] args) { //创建了资源Resource的 唯一对象 r Resource r = new Resource(); Input in = new Input(r);//线程 构造方法中传参 唯一对象r Output out = new Output(r);//线程 构造方法中传参 唯一对象r Thread tin = new Thread(in); Thread tout = new Thread(out); tin.start(); tout.start(); } }

浙公网安备 33010602011771号