Java基础—线程间通信

线程间的通信:其实就是多个线程操作同一资源,并且操作的动作不一样,最简单的例子:输入输出姓名、性别信息。
线程同步保证了不会出现名字与性别对性错误的情况,等待唤醒机制保证了不会出现一次输入多次输出或多次输入一次输出的情况。等待、唤醒必须是同一个锁,唤醒机制职能唤醒跟它持有相同锁的处于等待状态的线程。
输入输出姓名、性别信息的例子:

/*
 线程间通信,其实就是多个线程操作同一个资源。
 但操作的动作不同。
 名词提炼法:资源、两个不同的操作

 比如:一个线程往里面输入名字和性别,另一个线程取出名字和线程,分别简称为输入线程和输出线程。
       为了保证输入线程和输出线程操作的是同一资源,资源对象应以参数的形式传递,需要达到的目
       的是:输入线程输入一个,输出线程将其输出,为避免发生输入线程只输入了名字
       Cpu执行权就被输出线程抢走,以致输出错误的信息,应将使用线程同步;为避免输入线程输入一
       次,输出线程输出多次(或输入线程输入多次,而输出线程只输出一次)的情况,应定义一个标志
       位来判断是否可输入或可输出,在不可输入或不可输出时,先让线程等待,等被唤醒时判断标
       志位状态。

 步骤:1、定义一类描述资源:名字、性别、标志位;
       2、定义Input类,实现Runnable接口,一初始化就有了资源对象,复写run方法;
       3、定义Output类,实现接口Runnable,一出书画就有了字眼对象,复写run方法;
       4、通过Thread类建立线程;
       5、分别将Input、Output的子类对象以参数的形式传递给Thread类的构造函数;
       6、调用线程的start类开启线程。

 其他说明:这个是最简单的等待唤醒机制的体现,通俗的说,你操作一下,我操作一下,我操作结束
           ,进入等待之前会唤醒你,你操作结束,进入等待之前也要唤醒我。
           等待唤醒机制:只能唤醒使用同一个锁的处于等待状态的线程。
           wait()、notify()、notifyAll(),只能在同步代码中才能使用,并且使用的时候要加上
           该线程所属的锁(如:r.wait()、this.wait()),而锁是任意对象,所以这些方法被定义
           在Object类中。wait()有申明异常,在Runnable的run方法没有抛异常,所以只能try处理,
           不能抛。

 关键点:1、定义标志位来判断是否可输入或可输出;
         2、根据一个变量的值来选择输入的信息;(int i = 0 ;i = (i+1)%2;可以使i的值在0、1之间变换)
         3、线程执行的代码一般都是循环体;
         4、资源对象以参数的形式传递可以保证,输入和输出操作的是同一对象。
*/
//定义描述资源的类
class Resource
{
    String name;
    String sex;
    boolean flag = false;
}
//定义Input类
class Input implements Runnable
{
    private Resource r;
    Input(Resource r)
    {
        this.r = r;
    }
    public void run()
    {
        int i = 0;
        while(true)
        {
            synchronized(r)
            {
                if(r.flag)
                    try{r.wait();}catch(Exception e){}
                if(i == 0)
                {
                    r.name = "mack";
                    r.sex = "man";
                }
                else
                {
                    r.name = "莉莉";
                    r.sex = "女女";
                }
                i = (i+1)%2;
                r.flag = true;
                r.notify();
            }
        }       
    }
}
//定义Output类
class Output implements Runnable
{
    private Resource r;
    Output(Resource 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 InputOutput 
{
    public static void main(String[] args) 
    {
        //创建资源对象
        Resource r = new Resource();
        //将资源对象传递给Input和Output
        Input  in = new Input(r);
        Output ot = new Output(r);
        //创建线程
        Thread t1 = new Thread(in);
        Thread t2 = new Thread(ot);
        //开启线程
        t1.start();
        t2.start();
    }
}

生产消费问题:

/*
生产消费模型:生产一个消费一个,并且是多个线程生产,多个线程消费。
 名词提炼法:资源、生产操作、消费操作。

 判断标志if改while,是避免重复生产或重复消费的问题,用了while循环判断之后会出现
 所有线程都处于等待状态,所以需要将notify改为notifyAll。

 注:notifyAll唤醒的是全部处于等待状态的线程,而不仅仅是对方线程。
*/
//定义资源类
class Res
{
    String name;
    int count = 0;
    String toString;
    boolean flag = false;
    //生产的过程
    public synchronized void set(String name)
    {
        while(flag)
            try{this.wait();}catch(Exception e){}
        toString = name+"----"+count++;
        System.out.println("生产++++"+toString);
        this.notifyAll();
        flag = true;
    }
    //消费的过程
    public synchronized void get()
    {
        while(!flag)
            try{this.wait();}catch(Exception e){}
        System.out.println("消费===="+toString);
        this.notifyAll();
        flag = false;
    }
}
//定义生产类
class Product implements Runnable
{
    private Res r;
    Product(Res r)
    {
        this.r = r;
    }
    public void run()
    {
        while(true)
        {
            r.set("子弟土豆片");
        }
    }
}
//定义消费类
class Consumer implements Runnable
{
    private Res r;
    Consumer(Res r)
    {
        this.r = r;
    }
    public void run()
    {
        while(true)
        {
            r.get();
        }
    }
}
class  ProConTest
{
    public static void main(String[] args) 
    {
        //创建资源对象
        Res r = new Res();
        //创建生产、消费对象,并将资源对象传入
        Product pro = new Product(r);
        Consumer con = new Consumer(r);
        //通过Thread类创建线程
        Thread tp1 = new Thread(pro);
        Thread tp2 = new Thread(pro);
        Thread tc1 = new Thread(con);
        Thread tc2 = new Thread(con);
        //开启并执行该线程的方法
        tp1.start();
        tp2.start();
        tc1.start();
        tc2.start();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值