Java串行接口调用优化
准备面试总结下
1.CompletableFuture
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor( 10 , 20 , 1000L, TimeUnit.MICROSECONDS, new ArrayBlockingQueue( 100 )); public static void main(String[] args) throws ExecutionException, InterruptedException { CompletableFuture task1 = CompletableFuture.supplyAsync(() -> { try { System.out.println( "task1" ); Thread.sleep( 1000 ); } catch (InterruptedException e) { throw new RuntimeException(e); } return 1000 ; }, poolExecutor); CompletableFuture task2 = CompletableFuture.supplyAsync(() -> { try { System.out.println( "task2" ); Thread.sleep( 2000 ); } catch (InterruptedException e) { throw new RuntimeException(e); } return 2000 ; }, poolExecutor); CompletableFuture task3 = CompletableFuture.supplyAsync(() -> { try { System.out.println( "task3" ); Thread.sleep( 10000 ); } catch (InterruptedException e) { throw new RuntimeException(e); } return 5000 ; }, poolExecutor); Integer result1 = task1.get(); System.out.println(result1); Integer result2 = task2.get(); System.out.println(result2); Integer result3 = task3.get(); System.out.println(result3); CompletableFuture voidCompletableFuture = CompletableFuture.allOf(task1, task2, task3); poolExecutor.shutdown(); System.out.println( "执行完毕" ); } |
2.CoutDownLatch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | static HashMap map = new HashMap(); public static void main(String[] args) throws InterruptedException, ExecutionException { ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor( 10 , 20 , 1000L, TimeUnit.MICROSECONDS, new ArrayBlockingQueue( 100 )); CountDownLatch countDownLatch = new CountDownLatch( 3 ); Future task1 = poolExecutor.submit( new Callable() { @Override public Integer call() throws Exception { System.out.println( "任务1" ); Thread.sleep( 1000 ); System.out.println( "任务1结束" ); countDownLatch.countDown(); return 1000 ; } }); Future task2 = poolExecutor.submit( new Callable() { @Override public Integer call() throws Exception { System.out.println( "任务2" ); Thread.sleep( 500 ); System.out.println( "任务2结束" ); countDownLatch.countDown(); return 500 ; } }); Future task3 = poolExecutor.submit( new Callable() { @Override public Integer call() throws Exception { System.out.println( "任务3" ); Thread.sleep( 2000 ); System.out.println( "任务3结束" ); countDownLatch.countDown(); return 2000 ; } }); map.put( "task1" , task1.get()); map.put( "task2" , task1.get()); map.put( "task3" , task1.get()); System.out.println( "线程跑完了" ); countDownLatch.await(); System.out.println( "---------------任务执行结束-------------" ); poolExecutor.shutdown(); } |
3.阻塞获取异步调用结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool( 3 ); Future submit = executorService.submit( new Callable() { @Override public String call() throws Exception { Thread.sleep( 1000 ); return "Its done" ; } }); while ( true ){ if (submit.isDone()){ System.out.println(submit.get()); break ; } System.out.println(submit.isDone()); } } |
4.除了上面两个方法 还有 CyclicBarrier,Semaphore也都可以实现,可以自己尝试下
Java串口程序的调用
RXTX串口插件的使用方法(windows平台)
1、把rxtxParallel.dll、rxtxSerial.dll拷贝到:C:WINDOWSsystem32下。
2、如果是在开发的时候(JDK),需要把RXTXcomm.jar、rxtxParallel.dll、rxtxSerial.dll拷贝到…jre…libext下;如:D:Program FilesJavajre1.6.0_02libext
3、需要选中项目右键->Preperties->Java Build Path->Libraries->选择External Folder–>选择RXTXcomm.jar.
- 拷贝 RXTXcomm.jar 到 jrelibext目录中;
- 拷贝 rxtxSerial.dll 到 jrebin目录中;
- 拷贝 rxtxParallel.dll 到 jrebin目录中;
其中为jdk安装路径
下面是一些程序运行测试写的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | package com.serialport; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; import java.util.Enumeration; import java.util.HashSet; import java.util.TooManyListenersException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import com.readtable.HexTest; import gnu.io.CommPort; import gnu.io.CommPortIdentifier; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; import gnu.io.UnsupportedCommOperationException; /** * 这个是一个更加完善的串口调用及接收函数类 * @author Administrator * */ public class SerialReceiver extends Thread implements SerialPortEventListener{ HexTest hexT2 = new HexTest(); static CommPortIdentifier portId; // 串口通信管理类 static Enumeration> portList; // 有效连接上的端口的枚举 static InputStream inputStream; //从串口来数据的输入流 static OutputStream outputStream; // 向串口输出的流 static SerialPort serialPort; // 串口的引用 private static byte [] readBuffer = new byte [ 1024 ]; // 4k的buffer空间,缓存串口读入的数据 int numBytes; //buffer中的实际数据字节数 ,每一次读取的字节数据 // 堵塞队列用来存放读到的数据 private BlockingQueue msgQueue = new LinkedBlockingQueue(); //其他的常量设置 //端口是否打开了 boolean isOpen = false ; // 端口读入数据事件触发后,等待n毫秒后再读取,以便让数据一次性读完 public static int PARAMS_DELAY = 1000 ; // 延时等待端口数据准备的时间 public static int PARAMS_TIMEOUT = 2000 ; // 超时时间 public static String PARAMS_PORT = "COM4" ; // 端口名称 public static int PARAMS_RATE = 2400 ; // 波特率 public static int PARAMS_DATABITS = 8 ; // 数据位 public static int PARAMS_STOPBITS = 1 ; // 停止位 public static int PARAMS_PARITY = 1 ; // 奇偶校验 /** * SerialPort EventListene 的方法,持续监听端口上是否有数据流 */ @Override public void serialEvent(SerialPortEvent event) { // TODO Auto-generated method stub switch (event.getEventType()) { case SerialPortEvent.DATA_AVAILABLE: // 当有可用数据时读取数据 receTest(); break ; } } /** * 接收的数据进行打印测试 */ private void receTest() { try { numBytes = 0 ; while (inputStream.available() > 0 ) { numBytes += inputStream.read(readBuffer,numBytes, 1024 ); } if (numBytes > 0 ) { msgQueue.add( new Date() + "方法2接收的字节数为:" +numBytes+ " 收到的数据为:-----" + hexT2.arrayToHexStr(readBuffer, 0 , numBytes)); readBuffer = new byte [ 1024 ]; //重新构造缓冲对象,否则有可能会影响接下来接收的数据 } else { msgQueue.add( "额------没有读到数据" ); } } catch (IOException e) { } } /** * 根据串口名,获取串口接口 * @param portName * @return */ public SerialPort OpenSerialPort(String portName) { //获取设备上的所有端口 portList = CommPortIdentifier.getPortIdentifiers(); while (portList.hasMoreElements()) { // 获取相应串口对象 portId = (CommPortIdentifier) portList.nextElement(); System.out.println( "设备类型:--->" + portId.getPortType()); System.out.println( "设备名称:--->" + portId.getName()); //判断端口类型是否为串口 if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { // 判断如果输入的串口名对应的串口存在,就打开该串口 if (portId.getName().equals(portName)) { try { // 打开串口名字为COM_4(名字任意),延迟为2毫秒 serialPort = (SerialPort) portId.open( "COM_3" , 2000 ); return serialPort; } catch (PortInUseException e) { e.printStackTrace(); return null ; } } } } return null ; } /** * 打开串口的函数 * @param portName 串口名 * @param bitrate 波特率 * @param databit 数据位 * @param stopbit 停止位 * @param parity 校验方式:奇 偶 无 * @return */ public int OpenComport(String portName, int bitrate, int databit, int stopbit, int parity) { serialPort = OpenSerialPort(portName); if (serialPort != null ) { // 设置当前串口的输入输出流 try { inputStream = serialPort.getInputStream(); outputStream = serialPort.getOutputStream(); } catch (IOException e) { e.printStackTrace(); return 0 ; } // 给当前串口添加一个监听器 try { serialPort.addEventListener( this ); } catch (TooManyListenersException e) { e.printStackTrace(); return 0 ; } // 设置监听器生效,即:当有数据时通知 serialPort.notifyOnDataAvailable( true ); //给串口设置一些参数 try { // 比特率、数据位、停止位、奇偶校验位 serialPort.setSerialPortParams( bitrate,databit,stopbit,parity); } catch (UnsupportedCommOperationException e) { e.printStackTrace(); return 0 ; } return 1 ; } return 0 ; } @Override public void run() { // TODO Auto-generated method stub try { System.out.println( "--------------任务处理线程运行了--------------" ); while ( true ) { //如果堵塞队列中存在数据就将其输出 if (msgQueue.size() > 0 ) { System.out.println(msgQueue.take()); } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { SerialReceiver cRead = new SerialReceiver(); PARAMS_PORT = "COM3" ; // 端口名称 PARAMS_RATE = 2400 ; // 波特率 PARAMS_DATABITS = SerialPort.DATABITS_8; //数据位 PARAMS_STOPBITS = SerialPort.STOPBITS_1; // 停止位 PARAMS_PARITY = SerialPort.PARITY_EVEN; // 奇偶校验 int i = cRead.OpenComport(PARAMS_PORT,PARAMS_RATE,PARAMS_DATABITS, PARAMS_STOPBITS,PARAMS_PARITY); if (i == 1 ) { // 启动线程来处理收到的数据 cRead.start(); try { //发送指令 HexTest hexT = new HexTest(); byte [] bst = hexT.ReadTable07( 1 , 1 , 0 , 3 ); outputStream.write(bst, 0 ,bst.length); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { return ; } } } |
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持IT俱乐部。