3、线程通信EventHandler使用

作者:韩茹

公司:程序咖(北京)科技有限公司

鸿蒙巴士专栏作家

一、使用场景

EventHandler开发场景

EventHandler的主要功能是将InnerEvent事件或者Runnable任务投递到其他的线程进行处理,其使用的场景包括:

  • 开发者需要将InnerEvent事件投递到新的线程,按照优先级和延时进行处理。投递时,EventHandler的优先级可在IMMEDIATE、HIGH、LOW、IDLE中选择,并设置合适的delayTime。
  • 开发者需要将Runnable任务投递到新的线程,并按照优先级和延时进行处理。投递时,EventHandler的优先级可在IMMEDIATE、HIGH、LOW、IDLE中选择,并设置合适的delayTime。
  • 开发者需要在新创建的线程里投递事件到原线程进行处理。

EventRunner工作模式

EventRunner的工作模式可以分为托管模式和手动模式。两种模式是在调用EventRunner的create()方法时,通过选择不同的参数来实现的,详见API参考。默认为托管模式。

  • 托管模式:不需要开发者调用run()和stop()方法去启动和停止EventRunner。当EventRunner实例化时,系统调用run()来启动EventRunner;当EventRunner不被引用时,系统调用stop()来停止EventRunner。
  • 手动模式:需要开发者自行调用EventRunner的run()方法和stop()方法来确保线程的启动和停止。

二、EventHandler

EventHandler,允许在异步线程上发送和处理InnerEvent和Runnable对象。每个EventHandler实例都绑定一个线程,该线程有一个事件队列。线程周期性地从事件队列中检索事件,并将事件分派给EventHandler进行处理。EventHandler将事件或Runnable任务传递到线程的事件队列,并在事件或任务从事件队列中出来时执行它。

您可以使用EventHandler在不同的线程之间调度和处理事件和Runnable 对象,并将事件或Runnable 对象安排在特定的时间间隔内进行处理。

您可以使用此类中提供的方法发送同步或异步事件、延迟事件处理以及设置事件优先级。

您需要重写processEvent(ohos.eventhandler.InnerEvent)方法来处理事件。

EventHandler类的定义:

java.lang.Object|---ohos.eventhandler.EventHandler
public class EventHandler extends Object

EventHandler的属性Priority(优先级)介绍:

EventRunner将根据优先级的高低从事件队列中获取事件或者Runnable任务进行处理。

属性描述
Priority.IMMEDIATE表示事件被立即投递
Priority.HIGH表示事件先于LOW优先级投递
Priority.LOW表示事件优于IDLE优先级投递,事件的默认优先级是LOW
Priority.IDLE表示在没有其他事件的情况下,才投递该事件

EventHandler的主要方法介绍:

接口名描述
EventHandler(EventRunner runner)利用已有的EventRunner来创建EventHandler
current()在processEvent回调中,获取当前的EventHandler
processEvent(InnerEvent event)回调处理事件,由开发者实现
sendEvent(InnerEvent event)发送一个事件到事件队列,延时为0ms, 优先级为LOW
sendEvent(InnerEvent event, long delayTime)发送一个延时事件到事件队列,优先级为LOW
sendEvent(InnerEvent event, long delayTime, EventHandler.Priority priority)发送一个指定优先级的延时事件到事件队列
sendEvent(InnerEvent event, EventHandler.Priority priority)发送一个指定优先级的事件到事件队列,延时为0ms
sendSyncEvent(InnerEvent event)发送一个同步事件到事件队列,延时为0ms,优先级为LOW
sendSyncEvent(InnerEvent event, EventHandler.Priority priority)发送一个指定优先级的同步事件到事件队列,延时为0ms,优先级不可以是IDLE
postSyncTask(Runnable task)发送一个Runnable同步任务到事件队列,延时为0ms, 优先级为LOW
postSyncTask(Runnable task, EventHandler.Priority priority)发送一个指定优先级的Runnable同步任务到事件队列,延时为0ms
postTask(Runnable task)发送一个Runnable任务到事件队列,延时为0ms,优先级为LOW
postTask(Runnable task, long delayTime)发送一个Runnable延时任务到事件队列,优先级为LOW
postTask(Runnable task, long delayTime, EventHandler.Priority priority)发送一个指定优先级的Runnable延时任务到事件队列
postTask(Runnable task, EventHandler.Priority priority)发送一个指定优先级的Runnable任务到事件队列,延时为0ms
sendTimingEvent(InnerEvent event, long taskTime)发送一个定时事件到队列,在taskTime时间执行,如果taskTime小于当前时间,立即执行,优先级为LOW
sendTimingEvent(InnerEvent event, long taskTime, EventHandler.Priority priority)发送一个带优先级的事件到队列,在taskTime时间执行,如果taskTime小于当前时间,立即执行
postTimingTask(Runnable task, long taskTime)发送一个Runnable任务到队列,在taskTime时间执行,如果taskTime小于当前时间,立即执行,优先级为LOW
postTimingTask(Runnable task, long taskTime, EventHandler.Priority priority)发送一个带优先级的Runnable任务到队列,在taskTime时间执行,如果taskTime小于当前时间,立即执行
removeEvent(int eventId)删除指定id的事件
removeEvent(int eventId, long param)删除指定id和param的事件
removeEvent(int eventId, long param, Object object)删除指定id、param和object的事件
removeAllEvent()删除该EventHandler的所有事件
getEventName(InnerEvent event)获取事件的名字
getEventRunner()获取该EventHandler绑定的EventRunner
isIdle()判断队列是否为空
hasInnerEvent(Runnable runnable)根据指定的runnable参数,检查是否有还未被处理的任务。可以根据不同的入参进行检查,详见EventHandler

三、EventRunner

EventRunner,在当前线程中创建和管理事件队列。

调用run()方法后,EventRunner将从事件队列中连续检索事件,并将事件分派给匹配的EventHandler。然后将调用EventHandler#processEvent(InnerEvent)方法来处理事件。

EventRunner类定义。

java.lang.Object|---ohos.eventhandler.EventRunnerpublic final class EventRunner extends Object

EventRunner的主要方法介绍:

接口名描述
create()创建一个拥有新线程的EventRunner
create(boolean inNewThread)创建一个拥有新线程的EventRunner,inNewThread为true时,EventRunner为托管模式,系统将自动管理该EventRunner;inNewThread为false时,EventRunner为手动模式
create(String newThreadName)创建一个拥有新线程的EventRunner, 新线程的名字是 newThreadName
current()获取当前线程的EventRunner
run()EventRunner为手动模式时,调用该方法启动新的线程
stop()EventRunner为手动模式时,调用该方法停止新的线程

四、InnerEvent

InnerEvent,用于定义可以发送到EventHandler的事件的结构。

InnerEvent类的定义:

public final class InnerEvent
extends Object
implements Sequenceable

一个InnerEvent 对象,包含了一个额外的整数字段和一个额外的对象字段来携带特定数据。

InnerEvent的属性介绍:

属性描述
eventId事件的ID, 由开发者定义用来辨别事件
object事件携带的Object信息
param事件携带的long型数据

InnerEvent的构造函数是私有的。因此,需要调用get()方法来创建InnerEvent实例。该方法将从回收对象池中提取InnerEvent实例。

常用方法:

方法名描述
drop()释放一个事件实例
get()获得一个事件实例
get(int eventId)获得一个指定的eventId的事件实例
get(int eventId, long param)获得一个指定的eventId和param的事件实例
get(int eventId, long param, Object object)获得一个指定的eventId,param和object的事件实例
get(int eventId, Object object)获得一个指定的eventId和object的事件实例
PacMap getPacMap()获取PacMap,如果没有,会新建一个
Runnable getTask()获取Runnable任务
PacMap peekPacMap()获取PacMap
void setPacMap(PacMap pacMap)设置PacMap

更多方法请查看,官方API

五、流程逻辑

5.1 EventHandler投递InnerEvent事件

EventHandler投递InnerEvent事件,并按照优先级和延时进行处理,开发步骤如下:

  1. 创建EventHandler的子类,在子类中重写实现方法processEvent()来处理事件。
	 private static final int EVENT_MESSAGE_NORMAL = 1;private static final int EVENT_MESSAGE_DELAY = 2;private class MyEventHandler extends EventHandler {private MyEventHandler(EventRunner runner) {super(runner);}// 重写实现processEvent方法@Overridepublic void processEvent(InnerEvent event) {super.processEvent(event);if (event == null) {return;}int eventId = event.eventId;switch (eventId) {case EVENT_MESSAGE_NORMAL:// 待执行的操作,由开发者定义break;case EVENT_MESSAGE_DELAY:// 待执行的操作,由开发者定义break;default:break;}}}
  1. 创建EventRunner,以手动模式为例。
   EventRunner runner = EventRunner.create(false);// create()的参数是true时,则为托管模式
  1. 创建EventHandler子类的实例。
MyEventHandler myHandler = new MyEventHandler(runner);
  1. 获取InnerEvent事件。
   // 获取事件实例,其属性eventId, param, object由开发者确定,代码中只是示例。long param = 0L; Object object = null; InnerEvent normalInnerEvent = InnerEvent.get(EVENT_MESSAGE_NORMAL, param, object);InnerEvent delayInnerEvent = InnerEvent.get(EVENT_MESSAGE_DELAY, param, object);
  1. 投递事件,投递的优先级以IMMEDIATE为例,延时选择0ms和2ms。
// 优先级IMMEDIATE,投递之后立即处理,延时为0ms,该语句等价于同步投递sendSyncEvent(event1,EventHandler.Priority.IMMEDIATE);
myHandler.sendEvent(normalInnerEvent, 0, EventHandler.Priority.IMMEDIATE);
myHandler.sendEvent(delayInnerEvent, 2, EventHandler.Priority.IMMEDIATE); // 延时2ms后立即处理
  1. 启动和停止EventRunner,如果为托管模式,则不需要此步骤。
   runner.run();// 待执行操作runner.stop();// 开发者根据业务需要在适当时机停止EventRunner

5.2 EventHandler投递Runnable任务

EventHandler投递Runnable任务,并按照优先级和延时进行处理,开发步骤如下:

  1. 创建EventHandler的子类,创建EventRunner,并创建EventHandler子类的实例,步骤与EventHandler投递InnerEvent场景的步骤1-3相同。

  2. 创建Runnable任务。

   Runnable normalTask = new Runnable() {@Overridepublic void run() {// 待执行的操作,由开发者定义}};Runnable delayTask = new Runnable() {@Overridepublic void run() {// 待执行的操作,由开发者定义}};
  1. 投递Runnable任务,投递的优先级以IMMEDIATE为例,延时选择0ms和2ms。
   // 优先级为immediate,延时0ms,该语句等价于同步投递myHandler.postSyncTask(task1,EventHandler.Priority.immediate);myHandler.postTask(normalTask, 0, EventHandler.Priority.IMMEDIATE);myHandler.postTask(delayTask, 2, EventHandler.Priority.IMMEDIATE);// 延时2ms后立即执行
  1. 启动和停止EventRunner,如果是托管模式,则不需要此步骤。
   runner.run();// 待执行操作runner.stop();// 停止EventRunner

5.3 在新创建的线程里投递事件到原线程

EventHandler从新创建的线程投递事件到原线程并进行处理,开发步骤如下:

  1. 创建EventHandler的子类,在子类中重写实现方法processEvent()来处理事件。
   private static final int EVENT_MESSAGE_CROSS_THREAD = 1;private class MyEventHandler extends EventHandler {private MyEventHandler(EventRunner runner) {super(runner);}// 重写实现processEvent方法@Overridepublic void processEvent(InnerEvent event) {super.processEvent(event);if (event == null) {return;}int eventId = event.eventId;switch (eventId) {case EVENT_MESSAGE_CROSS_THREAD:Object object = event.object;if (object instanceof EventRunner) {// 将原先线程的EventRunner实例投递给新创建的线程EventRunner runner2 = (EventRunner) object;// 将原先线程的EventRunner实例与新创建的线程的EventHandler绑定EventHandler myHandler2 = new EventHandler(runner2) {@Overridepublic void processEvent(InnerEvent event) {// 需要在原先线程执行的操作}};int eventId2 = 1; long param2 = 0L; Object object2 = null; InnerEvent event2 = InnerEvent.get(eventId2, param2, object2);myHandler2.sendEvent(event2); // 投递事件到原先的线程}break;default:break;}}}
  1. 创建EventRunner,以手动模式为例。
   EventRunner runner = EventRunner.create(false);// create()的参数是true时,则为托管模式。
  1. 创建EventHandler子类的实例。
   MyEventHandler myHandler = new MyEventHandler(runner);
  1. 获取InnerEvent事件。
// 获取事件实例,其属性eventId, param, object由开发者确定,代码中只是示例。
long param = 0L; 
InnerEvent event = InnerEvent.get(EVENT_MESSAGE_CROSS_THREAD, param, EventRunner.current());
  1. 投递事件,在新线程上直接处理。
// 将与当前线程绑定的EventRunner投递到与runner创建的新线程中
myHandler.sendEvent(event);
  1. 启动和停止EventRunner,如果是托管模式,则不需要此步骤。
   runner.run();// 待执行操作runner.stop();// 停止EventRunner

六、完整

非托管情况:

// 全局:
public static final int CODE_DOWNLOAD_FILE1 = 1;
public static final int CODE_DOWNLOAD_FILE2 = 2;
public static final int CODE_DOWNLOAD_FILE3 = 3;// 线程A:
EventRunner runnerA = EventRunner.create(false);
runnerA.run(); // run之后一直循环卡在这里,所以需要新建一个线程run// 线程B:
// 1.创建类继承EventHandler
public class MyEventHandler extends EventHandler {private MyEventHandler(EventRunner runner) {super(runner);}@Overridepublic void processEvent(InnerEvent event) {super.processEvent(event);if (event == null) {return;}int eventId = event.eventId;switch (eventId) {case CODE_DOWNLOAD_FILE1: {// 待执行的操作,由开发者定义break;}case CODE_DOWNLOAD_FILE2: {// 待执行的操作,由开发者定义break;}case CODE_DOWNLOAD_FILE3: {// 待执行的操作,由开发者定义break;}default:break;}}
}// 2.创建MyEventHandler实例
MyEventHandler handler = new MyEventHandler(runnerA);// 3.向线程A发送事件
handler.sendEvent(CODE_DOWNLOAD_FILE1);
handler.sendEvent(CODE_DOWNLOAD_FILE2);
handler.sendEvent(CODE_DOWNLOAD_FILE3);// 4.runnerA不再使用后,退出
runnerA.stop();

托管情况:

// 全局:
public static final int CODE_DOWNLOAD_FILE1 = 1;
public static final int CODE_DOWNLOAD_FILE2 = 2;
public static final int CODE_DOWNLOAD_FILE3 = 3;// 1.创建EventRunner A:
EventRunner runnerA = EventRunner.create("downloadRunner"); // 内部会新建一个线程// 2.创建类继承EventHandler
public class MyEventHandler extends EventHandler {private MyEventHandler(EventRunner runner) {super(runner);}@Overridepublic void processEvent(InnerEvent event) {super.processEvent(event);if (event == null) {return;}int eventId = event.eventId;switch (eventId) {case CODE_DOWNLOAD_FILE1: {// 待执行的操作,由开发者定义break;}case CODE_DOWNLOAD_FILE2: {// 待执行的操作,由开发者定义break;}case CODE_DOWNLOAD_FILE3: {// 待执行的操作,由开发者定义break;}default:break;}}
}// 3.创建MyEventHandler实例
MyEventHandler handler = new MyEventHandler(runnerA);// 4.向线程A发送事件
handler.sendEvent(CODE_DOWNLOAD_FILE1);
handler.sendEvent(CODE_DOWNLOAD_FILE2);
handler.sendEvent(CODE_DOWNLOAD_FILE3);// 5.runnerA没有任何对象引入时,线程会自动回收
runnerA = null;

###七、示例代码

1、EventHandler投递InnerEvent事件

我们现在ability_main.xml中放一个按钮:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_parent"ohos:width="match_parent"ohos:padding="20vp"ohos:orientation="vertical"><Buttonohos:id="$+id:btn1"ohos:height="match_content"ohos:width="match_content"ohos:text="EventHandler投递InnerEvent事件"ohos:background_element="#eeeeee"ohos:padding="20vp"ohos:multiple_lines="true"ohos:text_size="20fp"ohos:margin="10vp"/></DirectionalLayout>

然后在MainAbility中处理该按钮的点击事件,投递InnerEvent事件:

package com.example.hanrueventhandler.slice;import com.example.hanrueventhandler.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;public class MainAbilitySlice extends AbilitySlice {private static final int EVENT_MESSAGE_NORMAL = 1;private static final int EVENT_MESSAGE_DELAY = 2;// 定义日志标签private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG");@Overridepublic void onStart(Intent intent) {super.onStart(intent);super.setUIContent(ResourceTable.Layout_ability_main);initComponent();}public void initComponent(){findComponentById(ResourceTable.Id_btn1).setClickedListener(component -> eventHandlerPostInnerEvent());}// 按钮1:EventHandler投递InnerEvent事件public void eventHandlerPostInnerEvent(){// 2.创建EventRunner,手动模式或者托管模式EventRunner runner = EventRunner.create(true);// create()的参数是true时,则为托管模式// 3.创建EventHandler子类的实例。MyEventHandler myHandler = new MyEventHandler(runner);// 4.获取InnerEvent事件。// 获取事件实例,其属性eventId, param, object由开发者确定。long param1 = 9527L;Object object1 = "我是王二狗";InnerEvent normalInnerEvent = InnerEvent.get(EVENT_MESSAGE_NORMAL, param1, object1);long param2 = 1314L;Object object2 = "鸿蒙巴士";InnerEvent delayInnerEvent = InnerEvent.get(EVENT_MESSAGE_DELAY, param2, object2);HiLog.info(LABEL," 。。。");// 5.投递事件,投递的优先级以IMMEDIATE为例,延时选择0ms和2ms// 优先级IMMEDIATE,投递之后立即处理,延时为0ms,该语句等价于同步投递sendSyncEvent(event1,EventHandler.Priority.IMMEDIATE);myHandler.sendEvent(normalInnerEvent, 0, EventHandler.Priority.IMMEDIATE); // 立即处理myHandler.sendEvent(delayInnerEvent, 2, EventHandler.Priority.IMMEDIATE); // 延时2ms后立即处理// 6.启动和停止EventRunner,如果为托管模式,则不需要此步骤。// runner.run();// 待执行操作// runner.stop();// 开发者根据业务需要在适当时机停止EventRunner}// 1.创建EventHandler的子类,在子类中重写实现方法processEvent()来处理事件。private class MyEventHandler extends EventHandler {private MyEventHandler(EventRunner runner) {super(runner);}// 重写实现processEvent方法@Overridepublic void processEvent(InnerEvent event) {super.processEvent(event);if (event == null) {return;}int eventId = event.eventId;long param = event.param;Object object = event.object;HiLog.info(LABEL,"子线程。。。线程ID"+Thread.currentThread().getId()+",线程名称:"+Thread.currentThread().getName());switch (eventId) {case EVENT_MESSAGE_NORMAL:// 待执行的操作,由开发者定义HiLog.info(LABEL," 子线程中要处理的操作1。。。"+param+","+ object.toString());break;case EVENT_MESSAGE_DELAY:// 待执行的操作,由开发者定义HiLog.info(LABEL," 子线程中要处理的操作2。。。"+param+","+ object.toString());break;default:break;}}}}

运行程序,并点击按钮1:

WX20210629-165544@2x

2、EventHandler投递Runnable任务

我们现在ability_main.xml中,再放一个按钮:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_parent"ohos:width="match_parent"ohos:padding="20vp"ohos:orientation="vertical">...<Buttonohos:id="$+id:btn2"ohos:height="match_content"ohos:width="match_content"ohos:text="EventHandler投递Runnable任务"ohos:background_element="#eeeeee"ohos:multiple_lines="true"ohos:padding="20vp"ohos:text_size="20fp"ohos:margin="10vp"/></DirectionalLayout>

然后在MainAbility中处理该按钮的点击事件,投递Runnable任务:

public void initComponent(){findComponentById(ResourceTable.Id_btn1).setClickedListener(component -> eventHandlerPostInnerEvent());findComponentById(ResourceTable.Id_btn2).setClickedListener(component -> eventHandlerPostRunnableTask());}// 2.EventHandler投递Runnable任务public void eventHandlerPostRunnableTask(){// 2.创建EventRunner,手动模式或者托管模式EventRunner runner = EventRunner.create(true);// create()的参数是true时,则为托管模式// 3.创建EventHandler子类的实例。MyEventHandler myHandler = new MyEventHandler(runner);// 4.创建Runnable任务。Runnable normalTask = new Runnable() {@Overridepublic void run() {// 待执行的操作,由开发者定义HiLog.info(LABEL,"子线程ID:"+Thread.currentThread().getId()+",子线程名称:"+Thread.currentThread().getName()+"--->Runnable的normalTask");}};Runnable delayTask = new Runnable() {@Overridepublic void run() {// 待执行的操作,由开发者定义HiLog.info(LABEL,"子线程ID:"+Thread.currentThread().getId()+",子线程名称:"+Thread.currentThread().getName()+"--->Runnable的delayTask");}};HiLog.info(LABEL," 。。。。。。");// 5.投递// 优先级为immediate,延时0ms,该语句等价于同步投递myHandler.postSyncTask(task1,EventHandler.Priority.immediate);myHandler.postTask(normalTask, 0, EventHandler.Priority.IMMEDIATE);myHandler.postTask(delayTask, 2, EventHandler.Priority.IMMEDIATE);// 延时2ms后立即执行// 6.启动和停止EventRunner,如果为托管模式,则不需要此步骤。// runner.run();// 待执行操作// runner.stop();// 停止EventRunner}

运行程序,并点击按钮2:

WX20210629-170936@2x

3、在新创建的线程里投递事件到原线程

我们现在ability_main.xml中,再放一个按钮:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_parent"ohos:width="match_parent"ohos:padding="20vp"ohos:orientation="vertical">...<Buttonohos:id="$+id:btn3"ohos:height="match_content"ohos:width="match_content"ohos:text="在新创建的线程里投递事件到原线程"ohos:background_element="#eeeeee"ohos:padding="20vp"ohos:multiple_lines="true"ohos:text_size="20fp"ohos:margin="10vp"/></DirectionalLayout>

然后在MainAbility中处理该按钮的点击事件,在新创建的线程里投递事件到原线程:

public void initComponent(){findComponentById(ResourceTable.Id_btn1).setClickedListener(component -> eventHandlerPostInnerEvent());findComponentById(ResourceTable.Id_btn2).setClickedListener(component -> eventHandlerPostRunnableTask());findComponentById(ResourceTable.Id_btn3).setClickedListener(component -> postInnerEventToOriginalThread());}// 3.在新创建的线程里投递事件到原线程public void postInnerEventToOriginalThread(){// 2.创建EventRunner,手动模式或者托管模式EventRunner runner = EventRunner.create(true);// create()的参数是true时,则为托管模式// 3.创建EventHandler子类的实例。MyEventHandler myHandler = new MyEventHandler(runner);// 4.获取InnerEvent事件。// 获取事件实例,其属性eventId, param, object由开发者确定。long param = 723L;// 注意:这里的第三个参数Object,要传入当前线程对象。InnerEvent event = InnerEvent.get(EVENT_MESSAGE_CROSS_THREAD, param, EventRunner.current());// 5.投递事件,将与当前线程绑定的EventRunner投递到与runner创建的新线程中myHandler.sendEvent(event);// 6.启动和停止EventRunner,如果为托管模式,则不需要此步骤。// runner.run();// 待执行操作// runner.stop();// 开发者根据业务需要在适当时机停止EventRunner}

然后我们在MyEventHandler中,再加一个case进行处理:

private class MyEventHandler extends EventHandler {private MyEventHandler(EventRunner runner) {super(runner);}// 重写实现processEvent方法@Overridepublic void processEvent(InnerEvent event) {super.processEvent(event);if (event == null) {return;}int eventId = event.eventId;long param = event.param;Object object = event.object;HiLog.info(LABEL,"子线程。。。线程ID"+Thread.currentThread().getId()+",线程名称:"+Thread.currentThread().getName());switch (eventId) {case EVENT_MESSAGE_NORMAL:// 待执行的操作,由开发者定义break;case EVENT_MESSAGE_DELAY:// 待执行的操作,由开发者定义break;case EVENT_MESSAGE_CROSS_THREAD:if (object instanceof EventRunner) {HiLog.info(LABEL," 子线程中要处理的操作3。。。"+param+","+ object.toString());// 将原先线程的EventRunner实例投递给新创建的线程EventRunner runner2 = (EventRunner) object;// 将原先线程的EventRunner实例与新创建的线程的EventHandler绑定EventHandler myHandler2 = new EventHandler(runner2) {@Overridepublic void processEvent(InnerEvent event) {// 需要在原先线程执行的操作HiLog.info(LABEL," 原先的线程。。。"+Thread.currentThread().getId()+","+Thread.currentThread().getName());HiLog.info(LABEL," 原先的线程。。。eventId"+event.eventId+",param:"+event.param+",object:"+event.object);}};int eventId2 = 1;long param2 = 9988L;Object object2 = "我是小白菜";InnerEvent event2 = InnerEvent.get(eventId2, param2, object2);myHandler2.sendEvent(event2); // 投递事件到原先的线程}break;default:break;}}}

运行程序,并点击按钮3:

WX20210629-174255@2x

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/352920.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT市场营销指南震撼出炉,你错过了?!

ChatGPT是一种基于AI技术的语言模型&#xff0c;它可以与用户进行对话和交互。它被广泛应用于各个领域&#xff0c;包括市场营销。作为一名市场营销人员&#xff0c;您可以使用ChatGPT来获得创意、解决问题和生成内容。 下面是190个ChatGPT提示&#xff0c;可帮助营销人员更好…

专业分析┃微电子专业介绍及发展前瞻

不知道提到微电子&#xff0c;你最先想到的是什么&#xff1f;芯片&#xff1f;卡脖子&#xff1f;摩尔定律&#xff1f; 因为近两年芯片被限制的原因&#xff0c;大家经常可以从各路媒体上看到“芯片”一词。微电子作为一个学科&#xff0c;简单的说&#xff0c;就是研究如何…

Cookie和session工作流程详解

目录 cookie机制 session会话 理解会话机制 Servlet中对Cookie和Session提供的 HttpServletrequest类中的方法&#xff1a; 模拟实现登录功能 首先实现功能分为两个界面&#xff1a; &#xff08;1&#xff09;登录页面代码&#xff08;前端代码&#xff09; (2) 编写Lo…

Mac - 鼠标拖尾特效 By CursorEffect2

目录 一.引言 二.安装 CursorEffect2 三.使用 CursorEffect2 四.使用效果 五.内存消耗 六.一键关闭 七.总结 一.引言 在自己搭建的 Hexo 博客上可以定义鼠标点击的特效&#xff0c;如图点击后可以产生彩色的斑点。 于是想着除了浏览 Hexo 博客外&#xff0c;能不能别的也…

MyBatis深入学习总结

MyBatis总结 MyBatis入门操作 简介 原始jdbc操作&#xff08;查询数据&#xff09; 原始jdbc操作&#xff08;插入数据&#xff09; 原始jdbc操作的分析 原始jdbbc开发存在的问题如下&#xff1a; 数据库连接创建、释放频繁造成系统资源的浪费从而影响系统性能sql语句在代…

window11中QQ登录“无法访问个人文件夹”解决方案

window11刚发行不久&#xff0c;安装各种软件或多或少会遇到各种bug&#xff0c;例如安装QQ后&#xff0c;打开时会提醒你“无法访问个人文件夹”而打开QQ失败。 可以通过改变你自己设置的个人文件夹的权限来解决这个问题。 找到文件夹所在位置&#xff0c;右击文件夹&#xf…

QQ登录显示无法访问个人文件夹解决办法

之前QQ登录出错&#xff0c;一直显示无法访问个人文件夹&#xff0c;是否自动修复个人文件权限 直接找到你安装qq的文件路径&#xff0c;右键--》授予访问权限--》删除访问&#xff0c;就可以正常登录了 &#xff01;

如何解决Windows10启动QQ时报错无法访问个人文件夹?

1、首先不要安装其他电脑管家&#xff0c;因为这会使Windows10自带的安全中心出现变化&#xff0c;第一步打开自带安全中心。 2、进入之后找到病毒和威胁防护&#xff0c;进入病毒和威胁防护设置。 3、进入病毒和威胁防护设置后&#xff0c;找到管理受控制文件夹访问权限。 4、…

启动QQ时无法访问个人文件夹XXX,是否自动修复个人文件夹权限

如图 点击确定显示修复权限失败 找到上图显示的文件路径 右键属性 -> 安全 -> 编辑 -> 选中Users -> 勾选完全控制

腾讯QQ登录“无法访问个人文件夹”解决方法

今天&#xff0c;登录QQ时出现“无法访问个人文件夹&#xff0c;个人文件将被保存到我的文档”的问题 上网搜索了一下&#xff0c;还是没有解决问题。然后自己思考了一下&#xff0c;可能与我修改了“我的文档”的路径有关&#xff0c;我刚刚安装的QQ个人文件夹也正好指定放在…

解决QQ显示“无法访问个人文件夹”方法

在qq登录的过程中&#xff0c;显示“无法访问个人文件夹”这样的提示&#xff0c;该怎解决&#xff1f; 尝试过把qq卸载之后重新装&#xff0c;改变一下qq的属性-兼容性&#xff0c;以及管理员的方式运行&#xff0c;查了不少的攻略&#xff0c;始终无法解决&#xff1b; 经过…

Win11 “qq无法访问个人文件夹”解决方法(原创)

今天登QQ&#xff0c;突然弹窗显示“qq无法访问个人文件夹”&#xff0c;网上搜了一堆方法都没用&#xff0c;也不想卸载重装qq&#xff0c;我就寻思是不是文件夹权限的问题。 右键显示的无法访问的个人文件夹&#xff0c;选择“安全”&#xff0c;我把Users的权限选中&#xf…

qq 微信 无法访问个人文件夹

昨天某个时刻开始&#xff0c;QQ会出现所有图片无法加载的状况&#xff0c;微信会出现截图发到聊天框是文件的问题。 一开始不以为然&#xff0c;直到第二天重启电脑发现两个软件都登陆不上去了。对应显示的是标题的关键字&#xff0c;因为问题已经解决就不截图了。 解决方案&…

android 新建桌面文件夹在哪里,添加并管理桌面文件夹

添加并管理桌面文件夹 我们在使用Android手机的时候&#xff0c;随着手机内安装的软件越来越多&#xff0c;比如说笔者的这个手机里&#xff0c;算了一下&#xff0c;一共装了110个应用程序&#xff0c;七个分页&#xff0c;每页显示16个图标。那么在这里我们设想一下&#xff…

Win11QQ无法访问个人文件夹

Win11QQ无法访问个人文件夹 #第一步 找到QQ文件存储的文件夹 #第二步 右键→属性→安全→User→编辑→User→完全控制→确定 #OK了 去试一试吧b(&#xffe3;▽&#xffe3;)d

C盘瘦身:QQ文件的清理及Group2文件夹

目录 问题解决方法 Windows 10 20H2 TIM 问题 最近C盘被撑爆了 使用SpaceSniffer一扫发现QQ的文件中有个Group2文件夹占了我17G 但使用QQ自带的个人文件夹清理却扫不到&#xff0c;据说直接删除会丢失近期所有群聊的聊天图片 解决方法 在这个地方找到了大神fsz1987给出的…

QQ个人文件夹保存位置无效

必须写文章谴责QQ这种垃圾软件 B 了 dog&#xff0c;腾讯家的QQ真没几个好用的。之前是PC版QQ群文件跳转回来显示错误bug&#xff0c;之后是手机QQ看点等各种消息bug&#xff0c;现在隔了几年了还有“个人文件夹保存位置无效”。根本没有改进&#xff01; QQ个人文件夹保存位…

Javamail使用IMAP同步QQ自定义文件夹问题

前言 最近使用Javamail同步QQ文件夹的时候发现,在QQ web端建立的文件夹,在手机端javamail却抛出FolderNotFoundExcetion的异常,这个困扰我几天了,我一度认为是javamail的bug.直到今天不经意间的一个发现,才解决了这个问题,以此来记录下! 不经意间的发现,验证截图:

QQ无法访问个人文件夹,修复失败问题

某一天QQ突然弹出一个【无法访问个人文件夹】点修复没用&#xff0c;卸载重下也没用&#xff0c;网上找了很多方法都没有用。 最后找到一个修改兼容性&#xff0c;成功启动。 右键→属性→兼容性→WindowsXP 虽然能启动&#xff0c;能用了&#xff0c;但是很不方便&#xff0…

foxmail本地文件夹同步服务器,foxmail同步QQ邮箱里的所有文件夹

随着微信消息的轰炸,我决定重拾邮箱。为了方便管理邮箱,我下载并试用了Foxmail和网易邮箱大师,Foxmail不确定用什么语言开发的,可能是C++或者Delphi(早期应该是Delphi,最新的版本不确定),而网易邮箱大师用的是基于duilib + directui进行开发的(微信PC客户端也是用这个进行…