美文网首页
synchronized简版Looper

synchronized简版Looper

作者: 陆元伟 | 来源:发表于2019-09-25 16:28 被阅读0次

    我们知道Looper的工作机制就是不断的从MessageQueue里面获取消息,没有消息的时候则等待,直到有消息到来,看Looper的源码发现阻塞等待和通知用的是linux的epoll,它是linux内核下高效的的异步唤醒机制。既然是等待和唤醒,那是不是只用java就可以处理了。于是利用synchronized实现一个简版的Looper

    Message,里面只是简单的一个数据,并且简单用string类型

    public class Message {
        public Handler target;
        public Message next;
        public String data;
        public Message(String data) {
            this.data = data;
        }
        @Override
        public String toString() {
            return "data:"+data;
        }
    }
    

    然后是Handler,也只是发送和处理两个简单方法

    public class Handler {
        Looper looper;
        public Handler(Looper looper) {
            this.looper = looper;
        }
        public void handlerMsg(Message msg) {
            System.out.println("[handlerMsg]"+Thread.currentThread().getName()+","+msg);
        }
        public void sendMsg(Message msg) {
            System.out.println("[sendMsg]"+Thread.currentThread().getName()+","+msg);
            msg.target = this;
            looper.mQueue.enqueueMessage(msg);
        }
    }
    

    然后是MessageQueue,一个enqueueMessage方法,存储message,一个next方法,获取message,一个quit方法,结束等待。

    public class MessageQueue {
        
        public Message mMessages;
        
        private boolean mQuitting;
        public Message nextMsg() {
            
            synchronized (this) {
                for(;;) {
                    Message p = mMessages;
                    if(p==null) {
                        try {
                            System.out.println("wait....");
                            wait();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    if(mQuitting) {
                        return null;
                    }
                    p=mMessages;
                    mMessages=mMessages.next;
                    return p;
                    
                }
            }
            
        }
         void quit() {
                synchronized (this) {
                    if (mQuitting) {
                        return;
                    }
                    mQuitting = true;
                    notifyAll();
                }
            }
        public int size() {
            int size=0;
            Message p = mMessages;
            while(p!=null) {
                size++;
                p=p.next;
            };
            return size;
        }
        public void enqueueMessage(Message msg) {
            synchronized (this) {
                if(mMessages==null) {
                    mMessages = msg;
                }else {
                    Message pre= mMessages;
                    Message p = pre.next;
                        while(p!=null) {
                            pre=p;
                            p=p.next;
                        };
                        pre.next = msg;
                }
                notifyAll();
            }
        }
    }
    

    Looper就简单了,从MessageQueue里面不断的获取消息,处理消息。

    public class Looper {
        MessageQueue mQueue=new MessageQueue();
        private static Looper sMainLooper;
        static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
        public void loop() {
            for(;;) {
                Message msg=mQueue.nextMsg();
                if(msg==null) {
                    return;
                }
                msg.target.handlerMsg(msg);
            }
        }
        public void quit() {
            mQueue.quit();
        }
        
        public static void prepareMainLooper() {
            prepare();
            synchronized (Looper.class) {
                if (sMainLooper != null) {
                    throw new IllegalStateException("The main Looper has already been prepared.");
                }
                sMainLooper = myLooper();
            }
        }
          private static void prepare() {
                if (sThreadLocal.get() != null) {
                    throw new RuntimeException("Only one Looper may be created per thread");
                }
                sThreadLocal.set(new Looper());
            }
         public static Looper getMainLooper() {
                synchronized (Looper.class) {
                    return sMainLooper;
                }
         }
         public static  Looper myLooper() {
                return sThreadLocal.get();
            }
    }
    
    
    public class LooperTest {
        static Handler handler;
        public static void main(String[] args) throws Exception {
            //模拟主线程
            Thread mainThread=new Thread(new Runnable() {
                @Override
                public void run() {
                    Looper.prepareMainLooper();
                    handler=new Handler(Looper.getMainLooper());
                    Looper.getMainLooper().loop();
                    System.out.println("quit");
                }
            });
            mainThread.setName("mainThead");
            mainThread.start();
            //延迟是等主线程的loop()执行
            Thread.sleep(100);
            //模拟其他线程,发送消息
            Thread t=new Thread() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    handler.sendMsg(new Message("1"));
                    handler.sendMsg(new Message("2"));
                    handler.sendMsg(new Message("3"));
                }
            };
            t.setName("otherThread1");
            t.start();
            //模拟其他线程,发送消息
            Thread t2=new Thread() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    handler.sendMsg(new Message("4"));
                    handler.sendMsg(new Message("5"));
                    handler.sendMsg(new Message("6"));
                }
            };
            t2.setName("otherThread2");
            t2.start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //调用退出
                    Looper.getMainLooper().quit();
                }
            }).start();
        }
    }
    

    打印的日志如下。

    wait....
    [sendMsg]otherThread1,data:1
    [sendMsg]otherThread1,data:2
    [sendMsg]otherThread1,data:3
    [sendMsg]otherThread2,data:4
    [sendMsg]otherThread2,data:5
    [sendMsg]otherThread2,data:6
    [handlerMsg]mainThead,data:1
    [handlerMsg]mainThead,data:2
    [handlerMsg]mainThead,data:3
    [handlerMsg]mainThead,data:4
    [handlerMsg]mainThead,data:5
    [handlerMsg]mainThead,data:6
    wait....
    quit
    

    当然我们这个是简单再简单不过的版本,只有发送和处理,消息也没有按照时间排序。但是处理整个流程和系统Looper大致相似。

    相关文章

      网友评论

          本文标题:synchronized简版Looper

          本文链接:https://www.haomeiwen.com/subject/cffwuctx.html