为了说明 Exchanger 的使用,本文假设一种场景。假设有一个连接缓存队列,有一个连接器负责创建连接,创建的连接会存储在队列里。另外一个释放连接器可以释放连接,从队列里移除连接。连接器每次会随机地创建 1 或 2 个连接。释放连接器只能每次释放 1 个连接。最后肯定会有连接队列满的时候,那时就可以进行连接队列的测试了。
要实现这一种场景,可以使用 Exchanger 来实现。可以查看代码清单 4。
清单 4. 使用 Exchanger 实现连接缓存队列的测试
// 假设建立连接的类是 Connection class Connection{ private String connName; private String ipAddress; public Connection(String connName,String ipAddString) { this.connName=connName; this.ipAddress=ipAddString; } ..... ... } public class ConnectionQueueDemo { // 使用交换器实现连接器与释放连接器之间资源的共享 private static Exchanger<LinkedList<Connection>> exconn = new Exchanger<LinkedList<Connection>>(); // 连接器 public class Connector implements Runnable{ private LinkedList<Connection> connQueue; private String ipAddress; public Connector(LinkedList<Connection> connQueue,String ipAddress) { this.connQueue=connQueue; this.ipAddress=ipAddress; } public void run() { boolean flag=true; while(flag){ // 每次连接随机的 1~2 个连接。 Random random = new Random(); int connNumb = (random.nextInt())%2 + 1; // 得到随机的 1~2 个连接数 if(connNumb > 1){ System.out.println("Connector creates 2 connection!"); }else{ System.out.println("Connector creates 1 connection!"); } for(int i=0; i<connNumb; i++){ Connection conn = new Connection("Connector", getIpAddress()); connQueue.add(conn); } // 休息 1 秒 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e1) { e1.printStackTrace(); } try { // 交换给释放连接器,让释放连接器工作! connQueue =(LinkedList<Connection>) exconn.exchange(connQueue); } catch (InterruptedException e) { e.printStackTrace(); } if(connQueue.size()==10){ System.out.println("The connection queue is full!! The programme is end!"); // 当队列满时,可以加入一些测试逻辑代码 .... ... flag=false; System.exit(0); }else{ System.out.println("After Disconnector, the size of the queue is "+connQueue.size()); } } } public String getIpAddress(){ return ipAddress; } } // 释放连接器 public class Disconnector implements Runnable { private LinkedList<Connection> connQueue; public Disconnector(LinkedList<Connection> connQueue) { this.connQueue=connQueue; } public void run() { boolean flag=true; while(flag){ System.out.println("Disconnector disconnects 1 connection!"); if(!connQueue.isEmpty()) connQueue.remove(0); // 休息 1 秒 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e1) { e1.printStackTrace(); } try { // 交换给连接器,让连接器工作! connQueue =(LinkedList<Connection>) exconn.exchange(connQueue); } catch (InterruptedException e) { e.printStackTrace(); } if(connQueue.size()==0){ System.out.println("There is no connection in the queue!"); }else{ System.out.println( "After Connector, the size of the queue is "+connQueue.size()); } } } } public static void main(String[] args) { LinkedList<Connection> connQueue = new LinkedList<Connection>(); ConnectionQueueDemo connectionQueueDemo = new ConnectionQueueDemoEx(); new Thread(connectionQueueDemo.new Connector(connQueue,"192.168.1.1")).start(); new Thread(connectionQueueDemo.new Disconnector(connQueue)).start(); } }
在 main 函数里是具体的 Demo 实现。新建了连接器和释放连接器两个线程,它们共享一个连接缓存队列。由于,连接器每次随机的连接的连接数要大于释放连机器释放的连接数,所以最后,连接队列会满。