Android系统运行架构之--生产-消费者模型详解

原创 2015年11月17日 17:42:09

一个系统是如何运行起来的?通过安卓的源码分析我们大概可以知道,Android在驱动层,在上层都采取生产-消费者模型来构建整个系统;因此对于生产-消费者模型的理解,就显得十分重要;首先通过下图,让大家对生产-消费者模型有一个初步认识:
这里写图片描述
生产者负责向队列提交任务,消费者从队列取出任务,然后进行消费;
有人问,为什么要设计个这么个模型来用在软件开发中;因为这个模型很简单,很方便的将一个任务分解开来,有利于多线程的并发;有利于适应现代多核处理器,有利于现代操作系统通过分配时间片的方式来进行任务的运行;
生产-消费者模型的运用,有利于计算机更高效,更安全的管理利用唯一的硬件资源;
下面讲解生产-消费者模型的实现要点:
(一)设计队列
(二)设计提交任务的机制
(三)设计消费者消费模式
队列的设计相对简单,利用数据结构的知识就可以完成。
首先是队列元素:


/**
 * 
 * @author 徐晔
 * @note 队列元素
 */
public class Message {
    public Runnable runnable;
    public Message next;
    public LooperHandler mHandler;
    public int id;
    public boolean flag = false;

    public void recycle() {
        mHandler = null;
        next = null;
        runnable = null;
    }

}

然后是队列压入,取出接口类:


public class MessageQueue {

    public Message start = null, end = null;
    private boolean waitflag = false;

    /** 构造队列 */
    public MessageQueue() {
        // 初始化一个链表
        start = new Message();
        end = new Message();
        start.next = end;
        end.next = start;
    }

    /**
     * 判断队列是否为空
     */
    public boolean isempty() {
        // 当头尾相遇时,队列为空
        if (start.next == end) {
            return true;
        } else {
            return false;
        }
    }

    /** 给队列插入任务 
     **  该方法是由生产者线程执行,因此需要在调用该方法的时候对队列进行一个锁操作
     */
    public void postMessage(Message msg) {
        System.out.println("插入任务");
        // 尾插法
        end.next.next = msg;
        msg.next = end;
        // 尾结点指向链表的最后一个元素
        end.next = msg;
        if (waitflag) {
            synchronized (this) {
                System.out.println("唤醒");
                //由于该对象在一个线程中执行,因此也就只有这么一个线程在等待,因此调用的是notify();
                notify();
            }
        }
    }

    /**
     * 移除执行的元素
     */
    private void remove(Message msg) {
        start.next = msg.next;
        if (start.next == end) {
            end.next = start;
        }
    }

    /**
     * 获取元素
     * 
     * @return
     */
    public Message next() {
        if (isempty()) {
            synchronized (this) {
                try {
                    waitflag = true;
                    System.out.println("进入等待");
                    //唤醒等待的线程
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("/**************************************************************/");
        System.out.println("获取下一个消息");
        waitflag = false;
        Message msg = start.next;
        remove(msg);
        return msg;
    }

}

第一个问题解决了,我们来看第二个问题:提交任务的机制?提交任务属于生产者线程给消费者线程提交任务,因此我们需要获取到消费者线程的任务队列的提交任务的接口;
下面是我的实现:


public class Looper {

    /** 线程自带的队列 */
    private MessageQueue queue = null;
    /** 利用ThreadLocal来建立Thread和Looper的一一对应关系 */
    private static ThreadLocal<Looper> loopdata = new ThreadLocal<Looper>();

    private Looper() {

    }

    private void setQueue(MessageQueue queue) {
        this.queue = queue;
    }

    /** 初始化该线程的队列 */
    public final static void prepare() {
        // 保证一个线程对应一个Looper,一个Looper包含一个MessageQueue
        if (loopdata.get() == null) {
            System.err.println("设置队列");
            Looper l = new Looper();
            //引出MessageQueue 
            l.setQueue(new MessageQueue());
            loopdata.set(l);
        }
    }

    //获取到和调用者线程对应的队列
    public final static Looper get() {
        return loopdata.get();
    }

    /** 给消费者线程的队列压入数据 */
    void sendMessage(Message msg) {
        //队列加锁很重要
        synchronized (queue) {
            queue.postMessage(msg);
        }
    }

    /** 开始处理消息 */
    public final static void Loop() {

        Looper loop = loopdata.get();
        MessageQueue mqueue = loop.queue;
        // 进入死循环,处理消息
        for (;;) {
            Message msg = mqueue.next();
            if (msg.mHandler == null) {
                msg.mHandler = new LooperHandler(loop);
            }
            msg.mHandler.HandlerMessage(msg);
            msg.recycle();
        }
    }

}

队列压入接口和消费接口


public class LooperHandler {
    private Looper mLooper;

    public LooperHandler(Looper looper) {
        this.mLooper = looper;
    }

    /** 处理消息 */
    void HandlerMessage(Message msg) {
        Runnable r=msg.runnable;
        if(r!=null){
            r.run();
        }
    }

    /** 将消息压入队列 */
    public void sendMessage(Message msg) {
        mLooper.sendMessage(msg);
    }

}

好了,通过以上的构建,我们大概构造了生产–消费者模型:测试代码如下:

//生产者a
public class Producer implements Runnable {

    private LooperHandler handler;
    private int number = 0;

    public Producer(LooperHandler handler) {
        this.handler = handler;
    }

    @Override
    public void run() {
        while (true) {
            number++;
            final Message msg = new Message();
            msg.mHandler = handler;
            msg.id=number;
            msg.runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("Producer执行了第" + msg.id + "个任务");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
                }
            };
            handler.sendMessage(msg);
            System.out.println("提交了" + number + "次");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

//生产者b

public class Producerb implements Runnable {

    private LooperHandler handler;
    private int number = 0;

    public Producerb(LooperHandler handler) {
        this.handler = handler;
    }

    @Override
    public void run() {
        while (true) {
            number++;
            final Message msg = new Message();
            msg.mHandler = handler;
            msg.id=number;
            msg.runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("Producerb执行了第" + msg.id + "个任务");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
                }
            };
            handler.sendMessage(msg);
            System.out.println("提交了" + number + "次");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

测试:


public class Customer {

    public static void main(String[] args) {

        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                new Thread(new Producer(new LooperHandler(Looper.get()))).start();
                new Thread(new Producer(new LooperHandler(Looper.get()))).start();
                Looper.Loop();
                super.run();
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                new Thread(new Producerb(new LooperHandler(Looper.get()))).start();
                Looper.Loop();
                super.run();
            }
        }.start();


    }

}

生产者-消费者模型在Android开发中的应用

话说生产者-消费者模型可是并发模型中的一个经典案例了,你可能会问,这种并发情况下,一般服务端程序用的比较多把,Android端的应用程序哪有什么并发情况。虽然事实如此,但是构建生产者-消费者模型,是线...
  • YanghuiNipurean
  • YanghuiNipurean
  • 2016年05月19日 15:43
  • 1740

Android 价值千万的java多线程<三>生产者消费者模型四种实现方法

生产者消费者模型 同步问题核心在于:如何保证同一资源被多个线程并发访问时的完整性。常用的同步方法是采用信号或加锁机制,保证资源在任意时刻至多被一个线程访问。Java语言在多线程编程上实现了完全对象...
  • WHB20081815
  • WHB20081815
  • 2017年03月24日 18:51
  • 476

生产者-消费者模型在Android开发中的应用

话说生产者-消费者模型可是并发模型中的一个经典案例了,你可能会问,这种并发情况下,一般服务端程序用的比较多把,Android端的应用程序哪有什么并发情况。虽然事实如此,但是构建生产者-消费者模型,是线...
  • weijinqian0
  • weijinqian0
  • 2016年05月25日 10:30
  • 262

生产者消费者模式

public class N { public static void main(String[] args) { Account ac = new Account(3, "Helen")...
  • qhairen
  • qhairen
  • 2015年04月18日 19:30
  • 367

多任务并发之生产者消费者模式应用

生产者-消费者模式大家都很熟悉,生产者负责生产数据,并存放到队列中,消费者负责从队列中取出数据来消费。可以看出生产者和消费者之间不直接通讯,是通过队列来通讯的。 生产者和消费者是抽象的概念,可以是线程...
  • guozebo
  • guozebo
  • 2016年05月28日 22:58
  • 3002

Android中简易实现生产者和消费者问题

1
  • u010712277
  • u010712277
  • 2016年11月21日 22:17
  • 496

黑马程序员——利用生产者和消费者模式讨论notify()方法的运用

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------     当使用多线程来同时运行多个任务时,可以通过锁来同步多个任务的行为,从而使得一个任务不会...
  • codeting
  • codeting
  • 2015年11月25日 21:20
  • 231

Android平台多线程实现生产者-消费者模型

本示例利用线程容器-ThreadPoolExecutor 运行消费者任务线程,基于公平锁机制,控制消费者线程的中断(公平锁相对非公平锁在性能上会有所牺牲,但在执行诸如下载大文件这样的耗时任务时,能体现...
  • zhangbuzhangbu
  • zhangbuzhangbu
  • 2014年05月14日 10:53
  • 1286

Java 生产者 与 消费者 的实际运用

生产者与消费者模式的实际运用
  • qq1013598664
  • qq1013598664
  • 2016年10月08日 23:24
  • 701

android生产者消费者模式

生产者消费者模式 生产者->仓库->消费者 生产者一直在生产放入仓库中。消费者一直从仓库中取出来消费。线程同步 package shengchan.xiaofei; import android.a...
  • kyrinleo
  • kyrinleo
  • 2014年01月13日 11:50
  • 1356
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android系统运行架构之--生产-消费者模型详解
举报原因:
原因补充:

(最多只允许输入30个字)