一起Talk Android吧(第三百六十七回:多线程之线程间通信)

Posted talk_8

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一起Talk Android吧(第三百六十七回:多线程之线程间通信)相关的知识,希望对你有一定的参考价值。

各位看官们,大家好,上一回中咱们说的是android中多线程之LOCK锁的例子,这一回中咱们介绍的例子是多线程之线程间通信。闲话休提,言归正转。让我们一起Talk Android吧!

概念介绍

看官们,我们在前面章回中介绍了使用同步技术解决线程间访问共享资源的问题。本章回中将介绍线程之间的通信,线程之间的通信就是线程之间相互发送通知来访问共享资源或者做其它任务。大家有没有注意到同步技术解决了线程访问共享资源时一致性的问题,但是不能控制访问共享资源的顺序,而线程间的通信正好可以解决此问题。

为了方便大家理解 ,我们还以生产者和消费为例子:生产者生产的商品如果太多了就会产生库存,需要等消费者消费完商品后才能继续生产商品。如果生产者一边生产一边通知消费者去消费不是更好吗?为了实现这个好的想法,我们引入了线程通信技术,其背后的原理就是唤醒/等待机制。比如生产者生产完商品后唤醒消费者去消费商品,同时让生产者处于等待状态,消费者收到唤醒通知后开始消费商品,消费完成后再去唤醒生产者生产商品,同时让消费者处于等待状态,这样交替运行就可以有序地生产和消费商品。

明白线程通信的原理后,我们介绍在程序中如何去实现,在程序中等待操作使用wait()方法,唤醒操作使用notify()/notifyAll()方法,通常情况下使用带all的方法,因为它可以唤醒所有处于等待状态的线程,而不带all的方法只能唤醒一个处于等待状态的线程,而且不能确定唤醒的线程就是我们想要的线程。

注意一下:这些方法是Object类的方法,不是线程专有的方法,因此每个对象都有这些方法,我们在使用时需要注意唤醒和等待操作的对象必须是相同的对象。

示例程序

接下来我们通过示例代码来演示线程之间的通信。

public class ThreadLock 
    public static void main(String[] args) 
        // 使用同步方法和普通唤醒来实现线程间的通信
        class ProducerAndCustomer 
            //临界资源或者叫共享资源
            private int criticalResource;

            public ProducerAndCustomer() 
                criticalResource = 0;
           

            public synchronized void produce() 
                //如果有共享资源,生产者停止生产,进行睡眠状态,等待消费者唤醒
                while (criticalResource > 0) 
                    try 
                        System.out.println("produce criticalResource = "+criticalResource+" sleeping");
                        this.wait();
                     catch (InterruptedException e) 
                        e.printStackTrace();
                    
                
                criticalResource += 1;
                System.out.println("produce finished CriticalResource : "+criticalResource);
                //生产者生产了共享资源,唤醒消费者去消费
                this.notify();
//                this.notifyAll();
            

            public synchronized void consume() 
                //如果没有共享资源,消费者停止生产,进行睡眠状态,等待生产者唤醒
                while (criticalResource <= 0) 
                    try 
                        System.out.println("consume CriticalResource = "+criticalResource+" sleeping");
                        this.wait();
                     catch (InterruptedException e) 
                        e.printStackTrace();
                    
                
                //消息者消费完共享资源,唤醒生产者生产资源
                criticalResource -= 1;
                System.out.println("consume finished CriticalResource : "+criticalResource);
                this.notify();
            
        

       ProducerAndCustomer obj = new ProducerAndCustomer();

        new Thread(()->
            for (int i=0; i<3; i++) 
                obj.produce();
            ,"Produce: ").start();

        new Thread(()->
            for (int i=0; i<3; i++) 
                obj.consume();
            ,"Consume: ").start();
    

上面的程序和上一章回的程序类似,还是生产者与消费者的问题,不同的地方是模拟生产和消费操作的方法是同步方法,而且这两个方法中关于生产和消费的操作上添加了条件:判断共享资源的数量,之前程序中模拟生产和消费的方法都是无条件运行。
编译并且运行上面的程序可以得到以下结果:

produce finished CriticalResource : 1
produce criticalResource = 1 sleeping
consume finished CriticalResource : 0
consume CriticalResource = 0 sleeping
produce finished CriticalResource : 1
produce criticalResource = 1 sleeping
consume finished CriticalResource : 0
consume CriticalResource = 0 sleeping
produce finished CriticalResource : 1
consume finished CriticalResource : 0

从上面的运行结果中可以看到生产者和消费者交替运行,不再像线程同步程序中的运行结果一样生产者和消费者单独运行。另外,共享资源的数量始终不超过1,这个是在生产和消费操作中添加限制条件导致的结果,符合我们的预期。

看官们,关于Android中多线程之线程间通信的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!

以上是关于一起Talk Android吧(第三百六十七回:多线程之线程间通信)的主要内容,如果未能解决你的问题,请参考以下文章

一起Talk Android吧(第三百八十七回:LiveData)

一起Talk Android吧(第三百八十七回:LiveData)

一起Talk Android吧(第三百零七回:控件的风格)

一起Talk Android吧(第四百六十七回:实现自定义ViewGroup中的测量功能)

一起Talk Android吧(第三百二十七回:Android中的约束布局)

一起Talk Android吧(第三百三十七回: Android中的Volley二)