问题
由于项目需要控制的硬件设备不支持双工,但是却需要做到人眼看不出的同时收发(收:接收其他设备的信息包,可能是UDP包;发:以一定间隔发送心跳包)
解决思路
在收的时候,暂停心跳线程,保证设备接受到的数据正常。
代码
为方便展示,将实现方法放入简易Demo中。主要实现思路:使用ReentrantLock 和 Condition 配合,通过引入一个false标志。实现输入go的时候,开始心跳线程;输入end的时候,暂停心跳线程。
1public class Demo{
2 // 使用ReentrantLock 和 Condition 配合
3 public static ReentrantLock lock = new ReentrantLock();
4 public static Condition condition = lock.newCondition();
5
6 // 是否让心跳线程 暂停的标志
7 private static boolean pauseFlag = false;
8
9 // 程序主入口
10 public static void main(String[] args) {
11 new CommandThread().start();
12 new HeartBeatThread().start();
13
14 }
15
16 // 使用静态内部类的方式,方便演示
17 // 心跳线程
18 public static class HeartBeatThread extends Thread{
19 int count = 0;
20 public void run() {
21 while(true) {
22 lock.lock();
23 try {
24 if(pauseFlag)
25 condition.await();
26 // 模拟心跳包,每次打印
27 System.out.println(count++);
28 TimeUnit.SECONDS.sleep(1);
29 } catch (InterruptedException e) {
30 e.printStackTrace();
31 } finally {
32 lock.unlock();
33 }
34 }
35 }
36 }
37
38 // 控制暂停线程,如果输入go为开始,end为暂停
39 public static class CommandThread extends Thread{
40 public void run() {
41 Scanner sc = new Scanner(System.in);
42 while(sc.hasNext()) {
43 String command = sc.nextLine();
44
45 if(command.equals("end")) {
46 pauseFlag = true;
47 System.out.println("end");
48 }else if(command.equals("go")) {
49 lock.lock();
50 System.out.println("go");
51 pauseFlag = false;
52 condition.signal();
53 lock.unlock();
54 }
55 }
56 sc.close();
57 }
58 }
59
60}
遇到的坑
尝试使用线程停止,然后再开启线程的方式
具体做法:具体做法使用Thread.interrupt() + break 的 通过捕获异常的方式去停止线程(单独Thread.interrupt()方法不一定会停止线程)
缺点:能够正常停止心跳线程,但是停止线程之后需要重新开启线程(线程停止之后是不能重新start的)