java多线程

本文探讨了Java中多线程间的通讯问题,通过两个版本的代码对比,讲解了如何利用等待和唤醒机制来实现线程间的同步。解决了因线程抢占CPU导致的数据不一致问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java多线程之间的通讯(等待和唤醒机制)


代码1:

/**
*@author StormMaybin
*@Date 2016-05-16
*@<description>线程之间的通讯(等待唤醒机制)</description>
*/
class Res
{
    String name;
    String sex;
}

class Input implements Runnable
{
    private Res r;
    Input (Res r)
    {
        this.r = r;
    }
    public void run()
    {
        int x  = 0;
        while (true)
        {
            synchronized (Input.class)
            {
                if (x == 0)
                {
                    r.name = "mike";
                    r.sex = "nan";
                }
                else
                {
                    r.name = "mary";
                    r.sex = "女";
                }
                x = (x + 1) % 2;
            }
        }
    }
}
class Output implements Runnable
{
    private Res r;
    Output (Res r)
    {
        this.r = r;
    }
    public void run ()
    {
        while (true)
        {
            synchronized (Input.class)
            {
                System.out.println (r.name+"..."+r.sex);
            }
        }
    }
}
class  InputOutputTest
{
    public static void main(String[] args) 
    {
        //System.out.println("Hello World!");
        Res r  = new Res();
        Input in = new Input(r);
        Output out = new Output(r);

        Thread t1 = new Thread (in);
        Thread t2 = new Thread (out);

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

==这个代码是一个有问题的代码,为什么呢?因为在控制输入的线程输入了性别或者姓名的时候,此时,控制输出的线程抢到cpu的执行权,打印了性别或者是姓名,但是这个姓名和性别不一定是匹配的!所以问题就出在这了!==


代码2:

class Res
{
    String name;
    String sex;
    boolean flag = false;
}

class Input implements Runnable
{
    private Res r;
    Input (Res r)
    {
        this.r = r;
    }
    public void run()
    {
        int x  = 0;
        while (true)
        {
            synchronized (r)
            {
                if (r.flag)
                {
                    try
                    {
                        r.wait();
                    }
                    catch (Exception e)
                    {
                    }
                }
                if (x == 0)
                {
                    r.name = "mike";
                    r.sex = "nan";
                }
                else
                {
                    r.name = "mary";
                    r.sex = "女";
                }
                x = (x + 1) % 2;
                r.flag = true;
                r.notify();
                //唤醒第一个等待的线程
            }
        }
    }
}
class Output implements Runnable
{
    private Res r;
    Output (Res r)
    {
        this.r = r;
    }
    public void run ()
    {
        while (true)
        {
            synchronized (r)
            {
                if(!r.flag)
                {
                    try
                    {
                        r.wait();
                    }
                    catch (Exception e)
                    {
                    }
                }
                System.out.println (r.name+"..."+r.sex);
                r.flag = false;
                r.notify();
            }
        }
    }
}
class  InputOutputTest
{
    public static void main(String[] args) 
    {
        //System.out.println("Hello World!");
        Res r  = new Res();
        Input in = new Input(r);
        Output out = new Output(r);

        Thread t1 = new Thread (in);
        Thread t2 = new Thread (out);

        t1.start();
        t2.start();
    }
}
  • 总结

wait()
notify()
notifyAll()
都使用在同步中,因为要对持有监视器(锁)的线程进行操作
所以要使用在同步中,因为只有在同步中才具有锁。

为什么这些操作线程的方法要定义在Object类中呢?
因为这些方法在操作同步中线程的时候,都必须要标识它们所操作线程
只有的锁,只有同一个锁上的被等待线程可以被同一个锁上notify唤醒*不可以对不同锁中的线程进行唤醒
也就是说,等待和唤醒必须是同一个锁。

而锁可以是任意对象,所以可以被任意对象调用的方法必须定义在Object类中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值