- Task scheduling management task execution, because of the particularity, some tasks need to be first in, first out, queuing, at the same time, the task can only be executed one by one
- As far as I know, there are three options:
– Handler, HandlerThread
– ExecutorService
– Action
- HandlerThread Tasks need to be executed in the HandlerThread of the worker thread. Messages are sent and processed by the Handler to ensure that the task is executed in a long sequence and the thread is not blocked.
private Handler eventHandler = null; HandlerThread handlerThread = new HandlerThread("WebSocketThread"); handlerThread.start(); eventHandler = new Handler(handlerThread.getLooper()) { @Override public void handleMessage(@NonNull Message msg) { internalHandler.handleEvent(msg); if (! externalHandlers.isEmpty()) { for (IEventHandler handler : externalHandlers) { handler.handleEvent(msg); }}}};Copy the code
-
ExecutorService
ExecutorService can execute sequentially from a single thread, or in parallel, by following execoring-related factory instructions.
public enum SingleExecutor { INSTANCE; ExecutorService executorService = Executors.newSingleThreadExecutor(); public ExecutorService getExecutorService() { return executorService; }}Copy the code
Submit performs Runnable through ExecutorService to implement task execution, and multiple tasks perform internal thread insertion for task scheduling.
- Custom task mechanism, cumbersome, not recommended. Need to maintain their own events and threads, prone to error.
public class Executor implements LifecycleObserver, Action.OnFinishedListener, Action.OnReadyListener { private static Executor sInstance = null; private final IWSServer wsServer; private final LinkedList<Action<? >> ongoingActions = new LinkedList<>(); private final List<Action<? >> pendingActions = new ArrayList<>(); private WorkThread curThread = null; private Executor(IWSServer server) { wsServer = server; } public static Executor getInstance(IWSServer server) { if (sInstance == null) { synchronized (Executor.class) { if (sInstance == null) { sInstance = new Executor(server); } } } return sInstance; } public void add(Action<? > action) { if (action == null) { return; } if (! action.isReady()) { addPendingAction(action); } else { addOngoingAction(action); }} public void onFinished(String response) {if (textutils.isempty (response)) { return; } wsServer.sendMessage(response); } @Override public void onReady(Action<? > action) { if (! pendingActions.contains(action)) { LogUtil.e("Invalid action in onReady"); return; } action.setOnReadyListener(null); pendingActions.remove(action); addOngoingAction(action); } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) private void onDestroy() { cancelThread(); } /** * join queue ** @param action */ private void addPendingAction(action <? > action) { pendingActions.add(action); action.setOnReadyListener(this); action.prepare(wsServer); } @param action */ private void addOngoingAction(action <? > action) { synchronized (ongoingActions) { ongoingActions.add(action); } if (! ongoingActions.isEmpty() && curThread == null) { curThread = new WorkThread(); curThread.start(); } } private void cancelThread() { if (curThread ! = null) { curThread.cancel(); curThread = null; } } private Action<? > popAction() { synchronized (ongoingActions) { return ongoingActions.isEmpty() ? null : ongoingActions.pop(); } } private void process(Action<? > action) { action.execute(); } private class WorkThread extends Thread { private boolean isCancelled = false; @Override public void run() { LogUtil.e("run work thread to process actions"); if (isCancelled) { return; } Action<? > current; while (! isCancelled && ((current = popAction()) ! = null)) { current.setOnFinishedListener(Executor.this); process(current); } LogUtil.e("finish work thread"); onFinish(); } public void cancel() { isCancelled = true; } public void onFinish() { curThread = null; }}}Copy the code
The Action class
public abstract class Action<T extends WSMessage<? >> { protected T request; protected OnFinishedListener onFinishedListener; protected OnReadyListener onReadyListener; public Action(T wsMessage) { request = wsMessage; } public abstract void execute(); public abstract boolean isReady(); public void setOnFinishedListener(OnFinishedListener listener) { onFinishedListener = listener; } public void setOnReadyListener(OnReadyListener listener) { onReadyListener = listener; } protected void notifyFinish(String response) { if (onFinishedListener ! = null) { onFinishedListener.onFinished(response); } } protected void prepare(IWSServer server) { } public interface OnReadyListener { void onReady(Action<? > action); } public interface OnFinishedListener { void onFinished(String response); }}Copy the code