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

Posted zjm1999

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程进阶之等待唤醒机制相关的知识,希望对你有一定的参考价值。

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

//资源
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(); 
}
}

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

以上是关于多线程进阶之等待唤醒机制的主要内容,如果未能解决你的问题,请参考以下文章

java 22 - 17 多线程之等待唤醒机制(接16)

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

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

多线程间的通讯之等待唤醒机制

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

Java多线程:阻塞队列与等待唤醒机制初探