synchronized简版Looper

我们知道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大致相似。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章