多线程进阶之等待唤醒机制

/*
 * 线程间通讯实例
 * 多个线程在处理同一资源,但是任务不同
 */

//资源
class Resource
{
    String name;
    String sex;
}
//输入
class Input implements Runnable
{
    Resource r;//类对象
    public Input(Resource r)//类对象做构造参数-->初始化资源
    {
        this.r=r;
    }
    public void run()
    {
        int x=0;
        while(true)
        {
            /*
             * 加上同步锁,因为输入输出任务共享资源,所以将资源对象r作为锁
             * 也是为了让输入输出处于同一同步锁中,这样输入就不会在输入姓名林玲还没有赋值完性别女
             * 时(周俊明被林玲覆盖),切换执行权
             */
            synchronized(r)
            {
            if(x==0)
              {
                r.name="周俊明";
                r.sex="男";
               }
                else
                {
                    r.name="林玲";
                    r.sex="女";
                }
            }

            x=(x+1)%2;//算法切换:不断由if和else切换
        }
    }
}
//输出
class Output implements Runnable
{
    Resource r;
    public Output(Resource r)
    {
        this.r=r;
    }
    public void run()
    {
        while(true)
        {
            synchronized(r)
            {
            System.out.println(r.name+"....."+r.sex);
            }
        }
    }
}
public class ResourceDemo {
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();
}
}

变身 :

/**
 * 等待/唤醒机制
 *
 * 涉及的方法:
 *
 * 1.wait():让线程处于冻结状态,被wait的线程会被存储到线程池中.
 * 2.notify():唤醒线程池中的一个线程(任意)
 * 3.notifyAll():唤醒线程池中的索引线程.
 *
 * 这些方法都必须定义在同步中
 * 因为这些方法是用于操作线程状态的方法
 * 必须要明确到底操作的是哪个锁上的线程
 *
 * 为什么操作线程的方法wait notify notifyAll定义在Object类中
 *
 * 因为这些方法是监视器的方法.监视器就是锁
 * 锁可以是任意的对象,任意的对象调用的方式一定定义在object类中
 *  */
//资源
class Resour
{
    String name;
    String sex;
    boolean flag=false;//标记
}
//输入
class Inputs implements Runnable
{
    Resour r;//类对象
    public Inputs(Resour r)//类对象做构造参数-->初始化资源
    {
        this.r=r;
    }
    public void run()
    {
        int x=0;
        while(true)
        {
            /*
             * 加上同步锁,因为输入输出任务共享资源,所以将资源对象r作为锁
             * 也是为了让输入输出处于同一同步锁中,这样输入就不会在输入姓名林玲还没有赋值完性别女
             * 时(周俊明被林玲覆盖),切换执行权
             */
            synchronized(r)
            {
                try {
                    if(r.flag)
                        r.wait(); //标明睡眠/唤醒同一锁上线程
                } catch (InterruptedException e) {
                    // TODO: handle exception
                }
            if(x==0)
              {
                r.name="周俊明";
                r.sex="男";
               }
                else
                {
                    r.name="林玲";
                    r.sex="女";
                }
            r.flag=true;
            r.notify();
            }

            x=(x+1)%2;//算法切换:不断由if和else切换
        }
    }
}
//输出
class Outputs implements Runnable
{
    Resour r;
    public Outputs(Resour r)
    {
        this.r=r;
    }
    public void run()
    {
        while(true)
        {
            synchronized(r)
            {
                try {
                    if(!r.flag)
                        r.wait();
                } catch (InterruptedException e) {

                }
            System.out.println(r.name+"....."+r.sex);
            r.flag=false;
            r.notify();
            }
        }
    }
}
public class ResourceDemo1 {
public static void main(String[] args) {
    //创建资源
    Resour r=new Resour();
    //创建任务
    Inputs in=new Inputs(r);
    Outputs out=new Outputs(r);
    //创建线程
    Thread t1=new Thread(in);
    Thread t2=new Thread(out); 

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

优化:

//资源
class Resours
{
    private String name;//资源私有
    private String sex;
    private boolean flag=false;//标记

    public synchronized void set(String name,String sex)
    {
        if(flag)
            try {this.wait();} catch (InterruptedException e) {} //标明睡眠/唤醒同一锁上线程
        this.name=name;
        this.sex=sex;
        flag=true;
        this.notify();
    }
    public synchronized void out()
    {
        if(!flag)
            try {this.wait();} catch (InterruptedException e) {}
        System.out.println(name+"..."+sex);
        flag=false;
        this.notify();
    }
}
//输入
class Inputce implements Runnable
{
    Resours r;//类对象
    public Inputce(Resours r)//类对象做构造参数-->初始化资源
    {
        this.r=r;
    }
    public void run()
    {
        int x=0;
        while(true)
        {
            /*
             * 加上同步锁,因为输入输出任务共享资源,所以将资源对象r作为锁
             * 也是为了让输入输出处于同一同步锁中,这样输入就不会在输入姓名林玲还没有赋值完性别女
             * 时(周俊明被林玲覆盖),切换执行权
             */
            if(x==0)
              {
                r.set("周俊明","男");
              }
                else
                {
                    r.set("林玲","女");
                 }
             x=(x+1)%2;//算法切换:不断由if和else切换
             }
        }
    }
//输出
class Outputce implements Runnable
{
    Resours r;
    public Outputce(Resours r)
    {
        this.r=r;
    }
    public void run()
    {
        while(true)
        {
            r.out();
        }
    }
}
public class ResourceDemo2 {
public static void main(String[] args) {
    //创建资源
    Resours r=new Resours();
    //创建任务
    Inputce in=new Inputce(r);
    Outputce out=new Outputce(r);
    //创建线程
    Thread t1=new Thread(in);
    Thread t2=new Thread(out); 

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

一不小心就暴露了真实姓名

原文地址:https://www.cnblogs.com/zjm1999/p/9969707.html

时间: 2024-10-13 03:26:42

多线程进阶之等待唤醒机制的相关文章

[javaSE] 多线程通信(等待-唤醒机制)

两个线程操作同一个资源,比如,输入和输出,操作同一个对象,此时两个线程会争夺cpu的执行权,随机的进行切换.我们想实现先输入再输出,顺序的执行 目标对象定义一个标记字段,进行判断,wait()和notify()方法 wait()方法,线程会处于等待状态,等待的线程位于内存中的线程池中 notify()方法,唤醒线程池中的线程 notifyAll()方法,唤醒全部线程 上面的方法,需要写在同步里面,并且需要标识锁 这些操作线程的方法定义在Object对象中,因为这些方法,要通过同一个锁对象来调用

线程间的通信--等待唤醒机制

1.多个线程操作相同的资源,但是操作动作不同,所以存在安全问题例如: public class Test { public static void main(String[] args) { Resource r = new Resource(); Input in = new Input(r); Output out = new Output(r); Thread tin = new Thread(in); Thread tout = new Thread(out); tin.start();

多线程等待唤醒机制之生产消费者模式

上篇楼主说明了多线程中死锁产生的原因并抛出问题--死锁的解放方案,那么在本篇文章,楼主将引用一个KFC生产汉堡,顾客购买汉堡的过程来说明死锁解决方案及多线程的等待唤醒机制. 简单地用一幅图来说明KFC生产汉堡,顾客来消费的过程: 场景分析: 资源类:Hamburger 设置汉堡数据:SetThread(生产者) 获取汉堡数据:GetThread(消费者) 测试类:HamburgerTest 不同种类的线程(生产者.消费者)针对同一资源(汉堡)的操作 当汉堡有存货的时候,汉堡师傅不再生产,顾客可消

java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

 *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时候才能消费,仓空则等待. *3.当消费者发现仓储没有产品可消费的时候,会唤醒等待生产者生产. *4.生产者在生产出可以消费的产品的时候,应该通知等待的消费者去消费. 下面先介绍个简单的生产者消费者例子:本例只适用于两个线程,一个线程生产,一个线程负责消费. 生产一个资源,就得消费一个资源. 代码如下: pub

java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)

1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以可以被任意对象调用的方法,定义在Object基类中. wait()方法:对此对象调用wait方法导致本线程放弃对象锁,让线程处于冻结状态,进入等待线程的线程池当中.wait是指已经进入同步锁的线程,让自己暂时让出同步锁,以便使其他正在等待此锁的线程可以进入同步锁并运行,只有其它线程调用notify方

多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)

一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name   sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. 为了解决上述问题中的安全问题(在存放线程进行存放操作的时候, 打印线程不能对共有数据进行操作),所以应当对两个线程       操作共有数据的代码部分进行同步(使用synchronized(),来进行同步, 注意 :使用同一个对象作为同步锁. 二.等待唤醒机制. 在上述案例实现过后运行,会发现:打印

java多线程的等待唤醒机制及如何解决同步过程中的安全问题

/* class Person{ String name; String sex; boolean flag = true; public void setPerson(String name, String sex){ this.sex=sex; this.name=name; } } class Input implements Runnable{ int x=0; Person p; Input(Person p){ this.p=p; } public void run(){ while

java多线程中的生产者与消费者之等待唤醒机制@Version1.0

一.生产者消费者模式的学生类成员变量生产与消费demo,第一版1.等待唤醒:    Object类中提供了三个方法:    wait():等待    notify():唤醒单个线程    notifyAll():唤醒所有线程2.为什么这些方法不定义在Thread类中呢?  这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象.  所以,这些方法必须定义在Object类中.3.当我们在使用多线程的时候有的时候需要,一条线程产生一个数据,另一条线程接着消费一个数据,一边生产一边消费,

JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是class对象 我们在上节验证了同步函数的锁是this,但是对于静态同步函数,你又知道多少呢? 我们做一个这样的小实验,我们给show方法加上static关键字去修饰 private static synchronized void show() { if (tick > 0) { try { Thread