为了说明 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 实现。新建了连接器和释放连接器两个线程,它们共享一个连接缓存队列。由于,连接器每次随机的连接的连接数要大于释放连机器释放的连接数,所以最后,连接队列会满。

本文通过一个连接缓存队列的应用场景介绍Exchanger的使用方法。该场景中,一个连接器负责创建并存储连接到队列中,而另一个释放连接器则负责从队列中移除连接。最终,队列会在连接器创建的连接数超过释放连接器移除的数量时达到满状态。
3104

被折叠的 条评论
为什么被折叠?



