前言
最近研究了Android中的消息机制的源码,理解了内部的调用过程以及内部原理后,试着用java实现了类似于Android的消息机制。
Handler.java:
public class Handler {
private MessageQueue mQueue;
private Looper mLooper;
//Handler的初始化,在主线程完成
public Handler(){
//获取主线程的Looper对象
mLooper = Looper.myLooper();
this.mQueue = mLooper.mQueue;
}
//发送消息 压入队列
public void sendMessage(Message msg){
msg.target = this;
mQueue.enqueueMessage(msg);
}
//转发
public void dispatchMessage(Message msg){
handleMessage(msg);
}
public void handleMessage(Message msg){
}
}
Messager.java:
public class Message {
public int what;
public Object obj;
Handler target;
@Override
public String toString() {
// TODO Auto-generated method stub
return obj.toString();
}
}
MessageQueue.java:
public class MessageQueue {
// 通过数组的结构存储Message对象
Message[] items;
// 消息入队和出队列的位置
int putIndex;
int takeIndex;
int count;
// 互斥锁
// 代码块加锁
/*
* synchronized(msg){
*
*
* }
*/
private Lock lock;
// 条件变量
private Condition notEmpty;
private Condition notFull;
public MessageQueue() {
// 消息队列应该要有大小限制
this.items = new Message[50];
this.lock = new ReentrantLock();
this.notEmpty = lock.newCondition();
this.notFull = lock.newCondition();
}
// 加入队列 子线程 生产
public void enqueueMessage(Message msg) {
try {
lock.lock();
while(count == items.length){
try {
/*
* synchronized(msg){
* queue.await();
* }
*/
notFull.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
items[putIndex] = msg;
// 循环取值
putIndex = (++putIndex == items.length) ? 0 : putIndex;
count++;
//有新的message对象,通知主线程
notEmpty.signalAll();
} finally {
lock.unlock();
}
}
// 出队列 主线程 消费
public Message next() {
Message msg = null;
try{
lock.lock();
while(count == 0){
try {
notEmpty.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
msg = items[takeIndex]; // 取出
items[takeIndex] = null; // 元素置空
takeIndex = (++takeIndex == items.length) ? 0 : takeIndex;
count--;
//使用了一个Message对象,通知子线程 可以继续生产
notFull.signalAll();
}finally{
lock.unlock();
}
return msg;
}
}
Looper.java:
public final class Looper {
//每一个主线程都会有一个Looper对象,Looper对象保存在ThreadLocal,保证了线程数据的隔离
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
//一个looper对象对应一个消息队列
MessageQueue mQueue;
//消息队列的初始化
private Looper(){
mQueue = new MessageQueue();
}
//Looper对象的初始化
public static void prepare(){
if(sThreadLocal.get()!=null){
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
//获取当前线程的Looper对象
public static Looper myLooper(){
return sThreadLocal.get();
}
//轮询消息队列
public static void loop(){
Looper me = myLooper();
if(me == null){
throw new RuntimeException();
}
MessageQueue queue = me.mQueue;
for(;;){
Message msg = queue.next();
if(msg == null){
continue;
}
msg.target.dispatchMessage(msg);
}
}
}
HandlerTest.java:
public class HandlerTest {
public static void main(String[] args) {
Looper.prepare();
final Handler handler = new Handler(){
public void handleMessage(Message msg) {
System.out.println(Thread.currentThread().getName()+",received:"+msg.toString());
};
};
for(int i =0;i<10;i++){
new Thread(){
@Override
public void run() {
while(true){
Message msg = new Message();
msg.what = 1;
synchronized (UUID.class) {
msg.obj = Thread.currentThread().getName()+",send message:"+UUID.randomUUID();
}
System.out.println(msg);
handler.sendMessage(msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
//开启轮询
Looper.loop();
}
}