Skip to content

Latest commit

 

History

History
588 lines (508 loc) · 10.6 KB

5-1-练习-妖的出现和解决.md

File metadata and controls

588 lines (508 loc) · 10.6 KB
layout title date updated tags categories permalink thumbnail toc comment notag top
5-1-练习-妖的出现和解决
2015-10-13
2015-10-13
Java多线程
Java多线程基础
Java多线程JDK15
Java多线程案例
true
true
false
false

妖的出现和解决

需求

  • 资源有姓名和性别。
  • 两个线程,
  • 一个负责给姓名和性别赋值,
    
  • 一个负责获取姓名和性别的值。
    
  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();

    }
}