场景:
每1个台设备每次上传文件,只能单个文件上传,假如A设备有10个文件,B设备有10个文件。我要让AB两个设备10文件同时上传,比如A设备正在上传文件1号其他9个文件进入队列等待,B设备也是正在上传文件1号其他9个文件进入队列等待。AB设备共用同一个队列(先进先出队列)只有等A设备第一个文件上传成功了,才能继续上传A的。B也是这样的。
demo1:
public static ConcurrentHashMap<Integer, ConcurrentLinkedQueue<String>> devicesUploadFileMap = new ConcurrentHashMap<>();
public static ConcurrentHashMap<Integer, Thread> waiters = new ConcurrentHashMap<>();
public static void main(String[] args) throws InterruptedException {
// 监听队列 线程.....
new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
while (true) { //监听队列中的数据......
Thread.sleep(1000L);
Set<Map.Entry<Integer, ConcurrentLinkedQueue<String>>> entries = devicesUploadFileMap.entrySet();
if (CollectionUtils.isEmpty(entries)) {
// System.out.println("无设备信息.... 无队列信息......");
continue;
}
//一台设备对应一个队列
for (Map.Entry<Integer, ConcurrentLinkedQueue<String>> entry : devicesUploadFileMap.entrySet()) {
final ConcurrentLinkedQueue<String> valueQueue = entry.getValue();
final Integer termSn = entry.getKey();
if (CommUtils.isNull(valueQueue) || valueQueue.isEmpty()) {
continue;
}
if (CommUtils.isNull(termSn)) {
continue;
}
//一台设备一个线程 一台设备多个文件......
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
String poll = valueQueue.poll(); //取出队列中的发送报文指令
if (CommUtils.isNull(poll)) {
//结束这个线程......
System.out.println("队列信息为null" + termSn);
break;
}
System.out.println("解析队列参数【" + poll + "】....下发到设备文件上传中...." + termSn);
waiters.put(termSn, Thread.currentThread());
LockSupport.park();//等待当前文件上传成功...挂起状态......
System.out.println(termSn + ":文件上传成功......." + poll);
}
waiters.remove(termSn);//处理完当前设备后,移除该线程
System.out.println("处理完" + termSn);
}
}).start();
devicesUploadFileMap.remove(termSn);
}
}
}
}).start();
Thread.sleep(3000L); // 让前面的线程跑起来
// 2台设备同时上传文件....
for (int i = 0; i < 2; i++) {
final int termSn = i;
new Thread(new Runnable() {
@Override
public void run() {
try {
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
for (int k = 1; k <= 10; k++) {
queue.offer("文件" + k);
}
devicesUploadFileMap.put(termSn, queue);
System.out.println(termSn + "塞入完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
//上传成功通知...
Thread.sleep(5000L); // 让前面的线程跑起来
new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
while (true) {
for (int i = 0; i < 2; i++) {
Thread.sleep(1000 * 10L); //10秒
Thread thread = waiters.get(i);
LockSupport.unpark(thread);//
}
}
}
}).start();
}
demo2:
public static ConcurrentHashMap<Integer, ConcurrentLinkedQueue<String>> devicesUploadFileMap = new ConcurrentHashMap<>();
public static ConcurrentHashMap<Integer, Thread> waiters = new ConcurrentHashMap<>();
public static ConcurrentHashMap<Integer, Thread> beingHandlerDevices = new ConcurrentHashMap<>();
public static void main(String[] args) throws InterruptedException {
// 监听队列 线程.....
new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
while (true) { //监听队列中的数据......
Thread.sleep(1000L);
Set<Map.Entry<Integer, ConcurrentLinkedQueue<String>>> entries = devicesUploadFileMap.entrySet();
if (CollectionUtils.isEmpty(entries)) {
// System.out.println("无设备信息.... 无队列信息......");
continue;
}
//一台设备对应一个队列
for (Map.Entry<Integer, ConcurrentLinkedQueue<String>> entry : devicesUploadFileMap.entrySet()) {
final Integer termSn = entry.getKey();
// final ConcurrentLinkedQueue queue = entry.getValue();
if (CommUtils.isNull(termSn)) {
continue;
}
if (!CommUtils.isNull(beingHandlerDevices.get(termSn))) {
// System.out.println("termSn:" + termSn + "正在处理文件.......");
continue;
}
//一台设备一个线程 一台设备多个文件......
new Thread(new Runnable() {
@Override
public void run() {
beingHandlerDevices.put(termSn, Thread.currentThread());
while (true) {
ConcurrentLinkedQueue<String> queue = devicesUploadFileMap.get(termSn);
String poll = queue.poll(); //取出队列中的发送报文指令
if (CommUtils.isNull(poll)) {
//结束这个线程......
System.out.println("id:" + Thread.currentThread().getId() +
",name:" + Thread.currentThread().getName() + "队列信息为:null" + termSn);
break;
}
System.out.println("id:" + Thread.currentThread().getId() +
",name:" + Thread.currentThread().getName() +
"解析队列参数【" + poll + "】....下发到设备文件上传中....termSn:" + termSn);
waiters.put(termSn, Thread.currentThread());
LockSupport.park();//等待当前文件上传成功...挂起状态......
System.out.println("termSn:" + termSn + ":文件上传成功:......." + poll);
}
waiters.remove(termSn);//处理完当前设备后,移除该线程
beingHandlerDevices.remove(termSn); //处理完当前设备后,移除正在处理的termSn
devicesUploadFileMap.remove(termSn);//移除设备信息
System.out.println("处理完" + termSn);
}
}).start();
// devicesUploadFileMap.remove(termSn);//移除设备信息
}
}
}
}).start();
Thread.sleep(3000L); // 让前面的线程跑起来
// 2台设备同时上传文件....
for (int i = 0; i < 2; i++) {
final int termSn = i;
new Thread(new Runnable() {
@Override
public void run() {
try {
for (int k = 1; k <= 5; k++) {
Thread.sleep(3000L); // 让前面的线程跑起来
ConcurrentLinkedQueue<String> termSnForQueue = devicesUploadFileMap.get(termSn);
if (CommUtils.isNull(termSnForQueue)) {
termSnForQueue = new ConcurrentLinkedQueue<>();
}
termSnForQueue.offer("文件" + k);
devicesUploadFileMap.put(termSn, termSnForQueue);
System.out.println("termSn:" + termSn + ",塞入第" + k + "文件");
}
System.out.println(termSn + "塞入完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
//上传成功通知...
Thread.sleep(5000L); // 让前面的线程跑起来
new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
while (true) {
for (int i = 0; i < 2; i++) {
Thread.sleep(1000 * 10L); //10秒
Thread thread = waiters.get(i);
LockSupport.unpark(thread);//
}
}
}
}).start();
}