分析一下Handler用法。
Message.java代码:
public class Message {
Handler targer;
public int what;
public Object obj;
@Override
public String toString() {
return obj.toString();
}
}
Looper.java
public final class Looper {
//每一个主线程都会有一个Looper对象
//Looper对象保存在ThreadLocal中,保证了线程数据的隔离
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//一个Looper对象,对应一个消息队列
MessageQueue mQueue;
private Looper(){
mQueue = new MessageQueue(); //消息队列的初始化
}
/**
* Looper对象的初始化
*/
public static void perpare(){
if(sThreadLocal.get() != null){
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());//保存到sThreadLocal中
}
/**
* 获取当前线程中的Looper对象
* @return
*/
public static Looper myLooper(){
return sThreadLocal.get();
}
/**
*轮询消息队列
*/
public static void loop(){
Looper me = myLooper();
if(me ==null){
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
MessageQueue queue = me.mQueue;
for(;;){
Message msg = queue.next();
if (msg == null) {
continue;
}
//转发给Handler
msg.targer.dispatchMessage(msg);
}
}
}
MessageQueue.java
public class MessageQueue {
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();
}
/**
* 加入队列(子线程运行)
* @param msg
*/
public void enqueueMessage(Message msg){
//System.out.println("加入队列");
try{
lock.lock();
//消息队列满了,子线程停止发送消息,阻塞
while(count == items.length){
try {
notFull.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
items[putIndex] = msg;
//循环取值
putIndex = (++putIndex == items.length) ? 0 : putIndex;
count++;
//有新的message对象,通知主线程
notEmpty.signalAll();
}finally{
lock.unlock();
}
}
/**
* 出队列(主线程运行)
* 消费
* @return
*/
public Message next(){
Message msg = null;
try{
//消息队列为空,主线程Looper停止轮询,阻塞
lock.lock();
while(count == 0){
try {
notEmpty.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
msg = items[takeIndex]; //取出
items[takeIndex]=null;//元素置空
takeIndex = (++takeIndex == items.length) ? 0 : takeIndex;
count--;
//使用了一个message对象,通知子线程,可以继续生产
notFull.signalAll();
}finally{
lock.unlock();
}
return msg;
}
}
Handler.java
public class Handler {
private MessageQueue mQueue;
private Looper mLooper;
//Handler初始化在主线程中完成
public Handler(){
//获取主线程Looper对象
mLooper = Looper.myLooper();
this.mQueue = mLooper.mQueue;
}
/**
* 发送消息,压入队列
* @param msg
*/
public void sendMessage(Message msg){
msg.targer = this;
mQueue.enqueueMessage(msg);
}
public void handleMessage(Message msg) {
}
/**
* 转发
* @param msg
*/
public void dispatchMessage(Message msg){
handleMessage(msg);
}
}
测试类:HandlerTest.java
public class HandlerTest {
public static void main(String[] args) {
//轮询器初始化
Looper.perpare();
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) { //拿到消息
System.out.println(Thread.currentThread().getName() + ",received:"+msg.toString());
}
};
//开启10个子线程不断向主线程发消息
for (int i = 0; i < 10; i++) {
new Thread(){
public void run(){
while(true){
Message msg = new Message();
msg.what = 1;
synchronized (UUID.class) {
msg.obj= Thread.currentThread().getName()+"send message:"+UUID.randomUUID().toString();
}
System.out.println(msg);
handler.sendMessage(msg); //发送消息
try {
Thread.sleep(1000); //每隔1s发一次
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.start();
}
//开启轮询
Looper.loop();
}
}
完~~
文 | 力卉编程
网友评论