java new handler_Java代码实现安卓Handler

Handler机制的写法非常巧妙,这种逻辑方式不仅仅对于安卓,对于其它的windows应用、Swing开发都有可以借鉴的地方,之前还在做安卓的时候就一直很想把代码分离出来。

这里,我就简单地实现了Handler的主要功能,并没有做很细致的配置。代码的整体结构完全参考了Handler(或者说是直接拷贝的),具体的实现中,消息队列使用的是PriorityQueue,消息元素继承自Delayed接口。

只要你用的还是Java,在JDK1.5之后任何地方都可以使用。

缺点显而易见,对象创建太多了!(可以优化)

PriorityQueue队列计时元素

这个类不仅局限于本次代码,同样适用于java.util.concurrent包下其它通过PriorityQueue实现的队列。

此元素标明了每个消息的延迟时间,模仿了Handler发送延迟消息的功能。

import java.util.concurrent.Delayed;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.TimeoutException;

/**

* 延迟队列元素

*

* @author ChenSS on 2017年9月13日

* @param

*/

public class DelayItem implements Delayed {

private long timeout;

private long endTime;

private T item;

public DelayItem(T item, long timeout) {

this.item = item;

this.timeout = timeout;

this.endTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS);

}

public DelayItem(T item, long timeout, TimeUnit unit) {

this.item = item;

this.timeout = timeout;

this.endTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeout, unit);

}

public T getItem() {

return this.item;

}

public long getTimeout() {

return timeout;

}

/**

* 重置结束时间

*/

public void reset() throws TimeoutException {

if (System.nanoTime() > endTime)

throw new TimeoutException("The current object has timeout, can not be reset");

this.endTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS);

}

/**

* 预计结束时间-当前时间 = 剩余停滞时间(当数值小于零时此对象可用)

*

* @return 纳秒(未达到超时时间对象不可用)

*/

@Override

public long getDelay(TimeUnit unit) {

return unit.convert((endTime - System.nanoTime()), TimeUnit.NANOSECONDS);

}

/**

* 取出结束时间最早的

*/

@Override

public int compareTo(Delayed other) {

if (other == this)

return 0;

if (other instanceof DelayItem) {

long diff = endTime - ((DelayItem>) other).endTime;

return (diff == 0) ? 0 : ((diff < 0) ? -1 : 1);

}

long diff = (getDelay(TimeUnit.NANOSECONDS) - other.getDelay(TimeUnit.NANOSECONDS));

return (diff == 0) ? 0 : ((diff < 0) ? -1 : 1);

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + ((item == null) ? 0 : item.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

DelayItem> other = (DelayItem>) obj;

if (item == null) {

if (other.item != null)

return false;

} else if (!item.equals(other.item))

return false;

return true;

}

}

Handler

源码直接拷贝自安卓的Handler,删除了对于我来说不需要的代码。

package com.yt.test.handler;

public abstract class Handler {

public Looper mLooper;

public MessageQueue mQueue;

public Handler() {

final Class extends Handler> klass = getClass();

// java.lang.Class.isAnonymousClass() 当且仅当底层类是匿名类,则返回true。

// java.lang.Class.isMemberClass() 返回true当且仅当底层类是成员类。

// java.lang.Class.isLocalClass()返回true,当且仅当基础类是局部类。

// 原本这是日志,说明Handler不要随便去new,容易内存溢出

if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass())) {

System.out.println("The following Handler class should be static or leaks might" + " + klass.getCanonicalName()");

}

mLooper = Looper.myLooper();

if (mLooper == null) {

throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");

}

mQueue = mLooper.mQueue;

}

public Handler(Looper looper) {

}

public final boolean sendMessage(Message msg) {

return sendMessage(msg, 0);

}

public final boolean sendMessage(int what, long delayMillis) {

Message msg = Message.obtain();

msg.what = what;

return sendMessage(msg, delayMillis);

}

public final boolean sendMessage(Message msg, long delayMillis) {

if (delayMillis < 0)

delayMillis = 0;

return sendMessageAtTime(msg, delayMillis);

}

public boolean sendMessageAtTime(Message msg, long delayMillis) {

MessageQueue queue = mQueue;

if (queue == null)

throw new RuntimeException(this + " sendMessageAtTime() called with no mQueue");

return enqueueMessage(queue, msg, delayMillis);

}

private boolean enqueueMessage(MessageQueue queue, Message msg, long delayMillis) {

msg.target = this;

return queue.enqueueMessage(msg, delayMillis);

}

public final void dispatchMessage(Message msg) {

handleMessage(msg);

}

abstract public void handleMessage(Message msg);

}

Looper

package com.yt.test.handler;

public class Looper {

static final ThreadLocal sThreadLocal = new ThreadLocal();

public MessageQueue mQueue = new MessageQueue();

public Thread mThread;

private Looper() {

}

private Looper(boolean quitAllowed) {

mThread = Thread.currentThread();

}

public static Looper myLooper() {

return sThreadLocal.get();

}

public static void prepare(boolean quitAllowed) {

if (sThreadLocal.get() != null) {

throw new RuntimeException("Only one Looper may be created per thread");

}

sThreadLocal.set(new Looper(quitAllowed));

}

public static void loop() {

final Looper me = myLooper();

if (me == null) {

throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");

}

final MessageQueue queue = me.mQueue;

for (;;) {

try {

Message msg = queue.next();

if (msg == null)

return;

msg.target.dispatchMessage(msg);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

Message

package com.yt.test.handler;

public class Message {

private static final Message MESSAGE = new Message();

public Handler target;

// 变量,用于定义此Message属于何种操作

public int what;

// 变量,用于定义此Message传递的信息数据,通过它传递信息

public Object obj;

// 变量,传递一些整型数据时使用

public int arg1;

// 变量,传递一些整型数据时使用

public int arg2;

public static Message obtain() {

return MESSAGE;

}

}

MessageQueue

使用了锁和优先级队列,

优先级队列的使用,对比每一个消息的延迟时间,取出最着急等待的消息;

锁主要用于阻塞线程,虽然取出了最着急等待的那个消息,如果系统时间没有达到可以处理这个消息的时间,那么就阻塞线程,等待时间的到达。

这是为了实现Handler发送延迟消息的功能。

package com.yt.test.handler;

import static java.util.concurrent.TimeUnit.NANOSECONDS;

import java.util.PriorityQueue;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.ReentrantLock;

public class MessageQueue {

private final transient ReentrantLock lock = new ReentrantLock();

private final PriorityQueue> q = new PriorityQueue<>();

private final Condition available = lock.newCondition();

private Thread leader = null;

public Message next() throws InterruptedException {

final ReentrantLock lock = this.lock;

lock.lockInterruptibly();

try {

for (;;) {

DelayItem first = q.peek();

if (first == null)

available.await();

else {

long delay = first.getDelay(NANOSECONDS);

if (delay <= 0) {

first = q.poll();

return first.getItem();

}

first = null;

// don't retain ref while waiting

if (leader != null)

available.await();

else {

Thread thisThread = Thread.currentThread();

leader = thisThread;

try {

available.awaitNanos(delay);

} finally {

if (leader == thisThread)

leader = null;

}

}

}

}

} finally {

if (leader == null && q.peek() != null)

available.signal();

lock.unlock();

}

}

public boolean enqueueMessage(Message msg, long uptimeMillis) {

final ReentrantLock lock = this.lock;

DelayItem item = new DelayItem(msg, uptimeMillis);

lock.lock();

try {

q.offer(item);

if (q.peek() == item) {

leader = null;

available.signal();

}

return true;

} finally {

lock.unlock();

}

}

}

参照安卓的调用方式

如果你想写一个windows应用,写Swing什么的,就用这样的方式实现

package com.yt.test.handler;

public class Test {

public static Handler sMainThreadHandler;

public static void main(String[] args) {

// 启动looper

Looper.prepare(true);

// 创建一个子线程(工作线程,比如加载Activity啊,初始化一堆的对象等等)

startWorkThread();

// 创建一个子线程与主线程通讯的处理器,有需要主线程处理的事情,子线程就通过这个Handler发消息

sMainThreadHandler = initMainHandler();

// 启动主线程的无限轮询

Looper.loop();

}

public static Handler initMainHandler() {

return new Handler() {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

//TODO: 处理不同的消息(安卓中是一堆类型强转跟消息传递的代码)

default:

// EG:创建一个新的Handler

Test.createActivity();

break;

}

}

};

}

public static void startWorkThread(){

new Thread(() -> {

try {

//延迟,确保Lopper进入循环

Thread.sleep(1000);

System.out.println(Thread.currentThread().getName()+ " :send msg");

//假设说子线程的作用就是发送消息,要主线程new一个Handler

sMainThreadHandler.sendMessageAtTime(new Message(), 3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}).start();

}

public static void createActivity() {

Handler handler = new Handler() {

@Override

public void handleMessage(Message msg) {

System.out.println(Thread.currentThread().getName()+ " :get msg");

}

};

System.out.println(Thread.currentThread().getName()+ " :send msg");

handler.sendMessage(new Message());

}

}

其实还可以很多的事情

比如说你要一个记日志的Handler啊,输出SQL语句的Handler啊,都可以,Looper从没说非得跑在主线程,你可以使用Looper写一个专门的LooperThread。

package com.yt.test.handler;

public class Test2 {

static Handler handler1;

static Handler handler2;

public static void main(String[] args) {

Thread handlerThread = new Thread(new Runnable() {

@Override

public void run() {

Looper.prepare(true);

handler1 = new Handler() {

@Override

public void handleMessage(Message msg) {

System.out.println("handler1 LOG:" + msg.obj);

}

};

handler2 = new Handler() {

@Override

public void handleMessage(Message msg) {

System.out.println("handler2 SQL:" + msg.obj);

}

};

Looper.loop();

}

});

handlerThread.setName("handlerThread");

handlerThread.setDaemon(true);

handlerThread.start();

try {

Thread.sleep(3000);

int count = 30;

while (count-- > 0) {

final int cn = count;

new Thread(() -> {

Message message = new Message();

String msg = "[" + Thread.currentThread().getName() + "]" + cn;

message.obj = msg;

if (cn % 2 == 0) {

handler1.sendMessage(message);

} else {

handler2.sendMessage(message);

}

}, "THREAD" + count).start();

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

Java中的Handler机制是Android开发中非常重要的一个概念,它是用来处理线程之间的通信的。在Java中,也可以使用Handler机制来实现线程之间的通信,这里简要介绍一下Java中的Handler机制。 Java中的Handler机制是基于线程池的,它可以将任务提交到线程池中执行,并且可以将执行结果返回给调用者。在Java中,可以使用Executor框架来实现线程池,同时可以使用Future接口来获取执行结果。 在Java中,Handler机制可以通过以下几个步骤来实现: 1. 创建一个线程池,可以使用Executor框架来实现。 2. 创建一个Callable接口的实现类,该实现类用来执行任务并返回结果。 3. 将Callable实现类提交到线程池中执行,可以使用submit()方法来实现。 4. 获取执行结果,可以使用Future接口来获取。 下面是一个简单的示例代码: ```java import java.util.concurrent.*; public class HandleJava { public static void main(String[] args) throws Exception { // 创建线程池 ExecutorService executor = Executors.newFixedThreadPool(1); // 创建Callable实现类 Callable<String> callable = new Callable<String>() { @Override public String call() throws Exception { // 执行任务 Thread.sleep(1000); return "Hello, world!"; } }; // 提交任务到线程池 Future<String> future = executor.submit(callable); // 获取执行结果 String result = future.get(); System.out.println(result); // 关闭线程池 executor.shutdown(); } } ``` 这个示例代码中,创建了一个线程池,然后创建了一个Callable实现类,将其提交到线程池中执行,并且使用Future接口来获取执行结果。最后关闭线程池。 需要注意的是,线程池一定要关闭,否则程序会一直运行下去,不会退出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值