Java串行接口调用优化
准备面试总结下
1.CompletableFuture
static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 20, 1000L, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<>(100)); public static void main(String[] args) throws ExecutionException, InterruptedException { CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() -> { try { System.out.println("task1"); Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } return 1000; }, poolExecutor); CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> { try { System.out.println("task2"); Thread.sleep(2000); } catch (InterruptedException e) { throw new RuntimeException(e); } return 2000; }, poolExecutor); CompletableFuture<Integer> 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<Void> voidCompletableFuture = CompletableFuture.allOf(task1, task2, task3); poolExecutor.shutdown(); System.out.println("执行完毕"); }
2.CoutDownLatch
static HashMap<String, Integer> map = new HashMap<String, Integer>(); 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<Integer> task1 = poolExecutor.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { System.out.println("任务1"); Thread.sleep(1000); System.out.println("任务1结束"); countDownLatch.countDown(); return 1000; } }); Future<Integer> task2 = poolExecutor.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { System.out.println("任务2"); Thread.sleep(500); System.out.println("任务2结束"); countDownLatch.countDown(); return 500; } }); Future<Integer> task3 = poolExecutor.submit(new Callable<Integer>() { @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.阻塞获取异步调用结果
public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(3); Future<String> submit = executorService.submit(new Callable<String>() { @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:\WINDOWS\system32下。
2、如果是在开发的时候(JDK),需要把RXTXcomm.jar、rxtxParallel.dll、rxtxSerial.dll拷贝到…\jre…\lib\ext下;如:D:\Program Files\Java\jre1.6.0_02\lib\ext
3、需要选中项目右键->Preperties->Java Build Path->Libraries->选择External Folder–>选择RXTXcomm.jar.
- 拷贝 RXTXcomm.jar 到 <JAVA_HOME>\jre\lib\ext目录中;
- 拷贝 rxtxSerial.dll 到 <JAVA_HOME>\jre\bin目录中;
- 拷贝 rxtxParallel.dll 到 <JAVA_HOME>\jre\bin目录中;
其中<JAVA_HOME>为jdk安装路径
下面是一些程序运行测试写的方法
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<String> msgQueue = new LinkedBlockingQueue<String>(); //其他的常量设置 //端口是否打开了 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; } } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。