5-1-Java多线程-练习-妖的出现和解决

来源:互联网 发布:苹果mac好用吗 编辑:程序博客网 时间:2024/04/30 09:48

妖的出现和解决

需求

  • 资源有姓名和性别。
  • 两个线程,
  • 一个负责给姓名和性别赋值,
  • 一个负责获取姓名和性别的值。

    1. 要求1,运行一下,解决程序的 “妖”的问题。
      分析过程:
      加入同步,必须保证同一个锁,解决妖的问题。

    2. 要求2,实现正确数据的间隔输出 如
      张飞–男
      rose–女女女
      张飞–男
      rose–女女女

    3. 要求3,对代码进行重构。
      将name,sex私有化,资源类提供对其访问的方法。

    4. 要求4,将程序改成JDK1.5的Lock Condition接口。

代码示例-需要分析的代码

代码

//描述资源。class Resource{    String name;    String sex;}//赋值线程任务class Input implements Runnable{    private Resource r;    //  private Object obj = new Object();    Input(Resource r)//任务一初始化就必须有要处理的资源。    {        this.r = r;    }    public void run()    {        int x = 0;        while(true)        {            if(x==0)            {                r.name = "张飞";                r.sex = "男";            }            else            {                r.name = "rose";                r.sex = "女女女女";            }            x = (x+1)%2;//实现切换。        }    }}//获取值线程任务class Output implements Runnable{    private Resource r ;    //  private Object obj = new Object();    Output(Resource r)    {        this.r = r;    }    public void run()    {        while(true)        {            System.out.println(r.name+"....."+r.sex);        }    }}class ThreadTest2{    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();    }}

 运行结果

张飞.....男rose.....女女女女rose.....女女女女张飞.....女女女女张飞.....女女女女rose.....男rose.....女女女女rose.....女女女女张飞.....女女女女rose.....女女女女rose.....女女女女张飞.....男张飞.....男rose.....女女女女

 分析

操作共享数据 name 和 sex

假设在–>处切换CPU执行权

if(x==0){    r.name = "张飞";    -->    r.sex = "男";}else{    r.name = "rose";    -->    r.sex = "女女女女";}

解决问题1

要求1,运行一下,解决程序的 “妖”的问题。
分析过程:
加入同步,必须保证同一个锁,解决妖的问题

代码示例

注意使用resouce做锁.(同步输入输出两个动作)

class Resource{    String name;    String sex;}//赋值线程任务class Input implements Runnable{    private Resource r;    //  private Object obj = new Object();    Input(Resource r)//任务一初始化就必须有要处理的资源。    {        this.r = r;    }    public void run()    {        int x = 0;        while(true)        {            synchronized(r)            {                if(x==0)                {                    r.name = "张飞";                    r.sex = "男";                }                else                {                    r.name = "rose";                    r.sex = "女女女女";                }            }            x = (x+1)%2;//实现切换。        }    }}//获取值线程任务class Output implements Runnable{    private Resource r ;    //  private Object obj = new Object();    Output(Resource r)    {        this.r = r;    }    public void run()    {        while(true)        {           synchronized(r)            {                System.out.println(r.name+"....."+r.sex);            }        }    }}class ThreadTest2{    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();    }}

运行结果

rose.....女女女女rose.....女女女女rose.....女女女女rose.....女女女女rose.....女女女女rose.....女女女女rose.....女女女女rose.....女女女女张飞.....男张飞.....男张飞.....男张飞.....男张飞.....男张飞.....男张飞.....男张飞.....

解决问题2

  1. 要求2,实现正确数据的间隔输出 如
    张飞–男
    rose–女女女
    张飞–男
    rose–女女女

代码

使用等待唤醒机制,使用flag作为判断是否等待

class Resource{    String name;    String sex;    //定义标记,    boolean flag = false;}//赋值线程任务class Input implements Runnable{    private Resource r;    //  private Object obj = new Object();    Input(Resource r)//任务一初始化就必须有要处理的资源。    {        this.r = r;    }    public void run()    {        int x = 0;        while(true)        {            synchronized(r)            {                if(r.flag)                    try{r.wait();}catch(InterruptedException e){}                if(x==0)                {                    r.name = "张飞";                    r.sex = "男";                }                else                {                    r.name = "rose";                    r.sex = "女女女女";                }                r.flag = true;                r.notify();            }            x = (x+1)%2;//实现切换。        }    }}//获取值线程任务class Output implements Runnable{    private Resource r ;    //  private Object obj = new Object();    Output(Resource r)    {        this.r = r;    }    public void run()    {        while(true)        {            synchronized(r)            {                if(!r.flag)                    try{r.wait();}catch(InterruptedException e){}                System.out.println(r.name+"....."+r.sex);                r.flag = false;                r.notify();            }        }    }}class ThreadTest2_2{    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

  1. 要求3,对代码进行重构。
    将name,sex私有化,资源类提供对其访问的方法。

代码示例

class Resource{    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 Input implements Runnable{    private Resource r;    Input(Resource r)//任务一初始化就必须有要处理的资源。    {        this.r = r;    }    public void run()    {        int x = 0;        while(true)        {            if(x==0)            {                r.set("张飞","男");            }            else            {                r.set("rose","女女女女");            }            x = (x+1)%2;//实现切换。        }    }}//获取值线程任务class Output implements Runnable{    private Resource r ;    Output(Resource r)    {        this.r = r;    }    public void run()    {        while(true)        {            r.out();        }    }}class ThreadTest2_3{    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();    }}

解决问题4

要求4,将程序改成JDK1.5的Lock Condition接口。
Lock替换了 同步函数或者同步代码块。
Condition替代了 监视器方法,将监视器方法从锁上分离出来,单独封装成Condition对象。

代码示例

class Resource{    private String name;    private String sex;    //定义标记,    private boolean flag = false;    //先创建锁对象。    private final Lock lock = new ReentrantLock();    //通过锁对象获取监视器对象。    private Condition con = lock.newCondition();    //赋值功能。    public  void set(String name,String sex)    {        lock.lock();        try{            if(flag)                try{con.await();}catch(InterruptedException e){}            this.name = name;            this.sex = sex;            flag = true;            con.signal();        }finally{            lock.unlock();        }    }    //获取值。    public  void out()    {        lock.lock();        try{            if(!flag)                try{con.await();}catch(InterruptedException e){}            System.out.println(name+"------"+sex);            flag = false;            con.signal();        }finally{            lock.unlock();        }    }}//赋值线程任务class Input implements Runnable{    private Resource r;    Input(Resource r)//任务一初始化就必须有要处理的资源。    {        this.r = r;    }    public void run()    {        int x = 0;        while(true)        {            if(x==0)            {                r.set("张飞","男");            }            else            {                r.set("rose","女女女女");            }            x = (x+1)%2;//实现切换。        }    }}//获取值线程任务class Output implements Runnable{    private Resource r ;    Output(Resource r)    {        this.r = r;    }    public void run()    {        while(true)        {            r.out();        }    }}class ThreadTest2_4{    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();    }}
0 0
原创粉丝点击