· 所谓“线程交接”,就是指同一个任务由于某种原因,需要安排在不同的线程中运行而产生的一种流程管理操作。
主线程 任务1 交接 结束 子线程中的任务2· 线程交接可以解决Qt中的多个线程操作同一个串口的问题,也可以用于流程性的编程。 Qt提供有一个串口操作类,但该类型不可以在多线程中共享。那么如果需要在多个线程中使用同一个串口,除了借助Win32的API外,就只能专门生成一个用于串口通信的线程了。
线程1 串口管理器 线程2 往串口1中写入"Hello World" 完成 串口1是否有收到消息 收到了"I got it" 往串口1中写入"Hello Kitty" 完成 串口1是否有收到消息 还没有 线程1 串口管理器 线程2· 在485总线上,所有设备的通信都应该是一收一发的,否则就会造成线路短接。为了防止多个线程操作串口导致收发过程冲突应加上线程锁。
线程1 串口管理器 线程2 我需要借用串口 我需要借用串口 借出串口使用权 往串口1中写入"Hello World" 完成 串口1是否有收到消息 收到了"I got it" 归还串口使用权 借出串口使用权 往串口1中写入"Hello Kitty" 完成 串口1是否有收到消息 还没有 串口1是否有收到消息 收到了"Thanks" 归还串口使用权 线程1 串口管理器 线程2· 这样我们就解决了Qt中的多线程操作同一个串口的问题。 使用线程交接还可以实现很复杂的流程控制。 这是普通的流程: · 这是普通的状态机:
· 这些都是单一线程就能够实现的传统流程。 除了这种简单的流程,还有一类比较复杂的:
· 双线程状态机最适合用来制作所有状态都按固定的规律循环变化的状态机。当主线程遇到主交点后,主线程阻塞,子线程从一个镜像交点开始被唤醒,执行到下一次遇到镜像交点时,子线程阻塞,主线程继续运行。 · 双线程离合机用于子线程长时间的操作。在子线程的长时间任务前设置一个异步交点,当子线程穿越异步交点时,主线程被唤醒,子线程仍然也在运行。在子线程需要与主线程进行数据同步的代码之前设置一个同步交点,当子线程遇到同步交点时,会等待主线程遇到主交点并阻塞后才继续执行。 · 上图是一个可以自由改变运行方式的离合机模型,它将单线程与双线程的功能合而为一。 线程交接的过程如下:
Created with Raphaël 2.2.0 开始交接 上锁 唤醒另一个线程 阻塞 解锁 完成交接· 只需要这么简单的操作,就可以实现非常复杂的多线程流程管理。除了在两个线程中使用,它也可以支持多个线程轮流唤醒。下面是它的Java实现:
public static final DebugLog log = new DebugLog(StaticThreadUtils.class); /** * 系统睡眠方法 * * @param ms * @return */ public static final boolean sleep(long ms) { try { Thread.sleep(Math.max(ms, 0)); return true; } catch (InterruptedException e) { log.println("sleep被强制唤醒"); e.printStackTrace(); } return false; } /** * 系统睡眠方法 * * @param ms * @param ns * @return */ public static final boolean sleep(long ms, int ns) { try { Thread.sleep(Math.max(ms, 0), Math.max(ns, 0)); return true; } catch (InterruptedException e) { log.println("sleep被强制唤醒"); e.printStackTrace(); } return false; } /** * 一步到位地等待 * * @param ms 停止等待的系统时间(毫秒) */ public static final void sleepUntil(long ms) { long delay = ms - System.currentTimeMillis(); if (delay <= 0) { Thread.yield(); } StaticThreadUtils.sleep(delay); } /** * 分步等待,防止系统休眠造成时间偏移 * * @param ms 停止等待的系统时间(毫秒) * @param proportion 拆分时间比例 * @param minDelay 最短允许拆分的最短时间 */ public static final void sleepUntil(long ms, double proportion, long minDelay) { if (proportion >= 1.0) { sleepUntil(ms); return; } else if (proportion < 0.0) { proportion = 0.0; } if (minDelay < 0l) { minDelay = 0l; } for (;;) { long delay = ms - System.currentTimeMillis(); if (delay <= 0) { Thread.yield(); return; } if (delay > minDelay) { // 拆分 delay *= proportion; if (delay < minDelay) { delay = minDelay; } } StaticThreadUtils.sleep(delay); } } /** * 让当前执行者睡眠 * * @param lock * @return */ public static final boolean sleep(Object lock) { return sleep(lock, -1); } /** * 让当前执行者睡眠 * * @param lock * @param ms * @return */ public static final boolean sleep(Object lock, long ms) { return sleep(lock, ms, null); } /** * 让当前执行者睡眠 * * @param lock * @param time * @param unit * @return */ public static final boolean sleep(Object lock, long time, TimeUnit unit) { // 为与Lock锁在形式上相仿,将同步区域扩大至全范围 synchronized (lock) { try { if (time == 0) { Thread.yield(); } else if (time < 0) { lock.wait(); } else { lock.wait(StaticDataUtils.getOrDefault(unit, TimeUnit.MILLISECONDS).toMillis(time)); } return true; } catch (InterruptedException e) { log.println("wait被异常打断"); e.printStackTrace(); } } return false; } /** * 让当前执行者睡眠,一步到位地等待 * * @param ms 停止等待的系统时间(毫秒) */ public static final void sleepUntil(Object lock, long ms) { long delay = ms - System.currentTimeMillis(); if (delay <= 0) { Thread.yield(); return; } StaticThreadUtils.sleep(lock, delay); } /** * 让当前执行者睡眠,分步等待,防止系统休眠造成时间偏移 * * @param ms 停止等待的系统时间(毫秒) * @param proportion 拆分时间比例 * @param minDelay 最短允许拆分的最短时间 */ public static final void sleepUntil(Object lock, long ms, double proportion, long minDelay) { if (proportion >= 1.0) { sleepUntil(lock, ms); return; } else if (proportion < 0.0) { proportion = 0.0; } if (minDelay < 0l) { minDelay = 0l; } for (;;) { long delay = ms - System.currentTimeMillis(); if (delay <= 0) { Thread.yield(); return; } if (delay > minDelay) { // 拆分 delay *= proportion; if (delay < minDelay) { delay = minDelay; } } StaticThreadUtils.sleep(lock, delay); } } /** * 交换组内的执行者。触发另一个使用相同锁的等待中的线程,然后等待。 * * @param lock */ public static final void exchange(Object lock) { synchronized (lock) { handover(lock, lock); } } /** * 交换组内的执行者。触发另一个使用相同锁的等待中的线程,然后等待。 * * @param lock * @param ms */ public static final void exchange(Object lock, long ms) { synchronized (lock) { handover(lock, lock, ms); } } /** * 交换组内的执行者。触发另一个使用相同锁的等待中的线程,然后等待。 * * @param lock * @param time * @param unit */ public static final void exchange(Object lock, long time, TimeUnit unit) { synchronized (lock) { handover(lock, lock, time, unit); } } /** * 交出这个组的执行权 * * @param from * @param to */ public static final void handover(Object from, Object to) { handover(from, to, -1); } /** * 交出这个组的执行权 * * @param from * @param to * @param ms */ public static final void handover(Object from, Object to, long ms) { handover(from, to, ms, null); } /** * 交出这个组的执行权 * * @param from * @param to * @param time * @param unit */ public static final void handover(Object from, Object to, long time, TimeUnit unit) { wake(to); sleep(from, time, unit); } /** * 交出这个组的执行权 * * @param from * @param to * @param toCond */ public static final void handover(Object from, Lock to, Condition toCond) { handover(from, to, toCond, -1); } /** * 交出这个组的执行权 * * @param from * @param to * @param toCond * @param ms */ public static final void handover(Object from, Lock to, Condition toCond, long ms) { handover(from, to, toCond, ms, null); } /** * 交出这个组的执行权 * * @param from * @param to * @param toCond * @param time * @param unit */ public static final void handover(Object from, Lock to, Condition toCond, long time, TimeUnit unit) { wake(to, toCond); sleep(from, time, unit); } /** * 唤醒该组内的随机一个成员 * * @param lock */ public static final void wake(Object lock) { synchronized (lock) { lock.notify(); } } /** * 唤醒该组内的所有成员 * * @param lock */ public static final void wakeAll(Object lock) { synchronized (lock) { lock.notifyAll(); } } /** * 让当前执行者睡眠 * * @param lock * @param cond * @return */ public static final boolean sleep(Lock lock, Condition cond) { return sleep(lock, cond, -1); } /** * 让当前执行者睡眠 * * @param lock * @param cond * @param ms * @return */ public static final boolean sleep(Lock lock, Condition cond, long ms) { return sleep(lock, cond, ms, null); } /** * 让当前执行者睡眠 * * @param lock * @param cond * @param time * @param unit * @return */ public static final boolean sleep(Lock lock, Condition cond, long time, TimeUnit unit) { try { lock.lock(); if (time == 0) { Thread.yield(); } else if (time < 0) { cond.await(); } else { cond.await(time, StaticDataUtils.getOrDefault(unit, TimeUnit.MILLISECONDS)); } return true; } catch (InterruptedException e) { log.println("wait被异常打断"); e.printStackTrace(); } finally { lock.unlock(); } return false; } /** * 让当前执行者睡眠,一步到位地等待 * * @param ms 停止等待的系统时间(毫秒) * @return */ public static final boolean sleepUntil(Lock lock, Condition condition, long ms) { try { lock.lock(); condition.awaitUntil(new Date(ms)); return true; } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } return false; } /** * 交换组内的执行者。触发另一个使用相同锁的等待中的线程,然后等待。 * * @param lock * @param cond */ public static final void exchange(Lock lock, Condition cond) { handover(lock, cond, cond); } /** * 交换组内的执行者。触发另一个使用相同锁的等待中的线程,然后等待。 * * @param lock * @param cond * @param ms */ public static final void exchange(Lock lock, Condition cond, long ms) { handover(lock, cond, cond, ms); } /** * 交换组内的执行者。触发另一个使用相同锁的等待中的线程,然后等待。 * * @param lock * @param cond * @param time * @param unit * @return */ public static final void exchange(Lock lock, Condition cond, long time, TimeUnit unit) { handover(lock, cond, cond, time, unit); } /** * 交出这个组的执行权 * * @param from * @param fromCond * @param to */ public static final void handover(Lock from, Condition fromCond, Object to) { handover(from, fromCond, to, -1); } /** * 交出这个组的执行权 * * @param from * @param fromCond * @param to * @param ms */ public static final void handover(Lock from, Condition fromCond, Object to, long ms) { handover(from, fromCond, to, ms, null); } /** * 交出这个组的执行权 * * @param from * @param fromCond * @param to * @param time * @param unit */ public static final void handover(Lock from, Condition fromCond, Object to, long time, TimeUnit unit) { wake(to); sleep(from, fromCond, time, unit); } /** * 交出这个组的执行权 * * @param from * @param fromCond * @param to * @param toCond */ public static final void handover(Lock from, Condition fromCond, Lock to, Condition toCond) { handover(from, fromCond, to, toCond, -1); } /** * 交出这个组的执行权 * * @param from * @param fromCond * @param to * @param toCond * @param ms */ public static final void handover(Lock from, Condition fromCond, Lock to, Condition toCond, long ms) { handover(from, fromCond, to, toCond, ms, null); } /** * 交出这个组的执行权 * * @param from * @param fromCond * @param to * @param toCond * @param time * @param unit */ public static final void handover(Lock from, Condition fromCond, Lock to, Condition toCond, long time, TimeUnit unit) { wake(to, toCond); sleep(from, fromCond, time, unit); } /** * 交出这个组的执行权 * * @param lock * @param fromCond * @param toCond */ public static final void handover(Lock lock, Condition fromCond, Condition toCond) { try { lock.lock(); handover(lock, fromCond, lock, toCond); } finally { lock.unlock(); } } /** * 交出这个组的执行权 * * @param lock * @param fromCond * @param toCond * @param ms */ public static final void handover(Lock lock, Condition fromCond, Condition toCond, long ms) { try { lock.lock(); handover(lock, fromCond, lock, toCond, ms); } finally { lock.unlock(); } } /** * 交出这个组的执行权 * * @param lock * @param fromCond * @param toCond * @param time * @param unit */ public static final void handover(Lock lock, Condition fromCond, Condition toCond, long time, TimeUnit unit) { try { lock.lock(); handover(lock, fromCond, lock, toCond, time, unit); } finally { lock.unlock(); } } /** * 唤醒该组内的随机一个成员 * * @param lock * @param cond */ public static final void wake(Lock lock, Condition cond) { try { lock.lock(); cond.signal(); } finally { lock.unlock(); } } /** * 唤醒该组内的所有成员 * * @param lock * @param cond */ public static final void wakeAll(Lock lock, Condition cond) { try { lock.lock(); cond.signalAll(); } finally { lock.unlock(); } }