需求:CS 架構的客戶端批量打印功能要做到控制單個客戶端操作,不可多客戶端同時操作批量打印,因爲批量打印調的後臺接口流水碼生成是續流的,任何一個Client調用都續流,多客戶端同時調用批量打印,一次批量打印出的流水碼就可能跳碼。接口服務是分佈式的,如果單服務接口,可以用同步鎖來實現。
思路:利用 redis 緩存標識是否有 Client 正在使用批量打印功能,操作批量打印功能時都查詢(查詢服務接口分佈式的)一次這個緩存標識,沒 Client 操作中就可操作批量打印功能,同時標識有客戶端正在操作中,不讓別的客戶端操作,批量打印操作完成之後釋放操作權限(批量打印異常也要釋放),標識沒有客戶端正在操作。
每個Client 操作批量打印功能前查詢這個標識時利用分佈式鎖技術,可參考博文1 和 博文2,誰先操作誰先搶到查詢標識的權限,按查詢標識結果提示是否等待一段時間再操作批量打印。
這個思路設計待測試,理論上應該是行得通的。
猿友們若有好的思路建議,歡迎留言。
測試結果出來了:
2020-04-04 14:13:58 Thread[客戶端窗口10,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:58 Thread[客戶端窗口18,5,main] 批量打印中
2020-04-04 14:13:58 Thread[客戶端窗口2,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:58 Thread[客戶端窗口13,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:58 Thread[客戶端窗口11,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:58 Thread[客戶端窗口5,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:58 Thread[客戶端窗口3,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:58 Thread[客戶端窗口15,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:58 Thread[客戶端窗口18,5,main] 批量打印完成
2020-04-04 14:13:59 Thread[客戶端窗口17,5,main] 批量打印中
2020-04-04 14:13:59 Thread[客戶端窗口19,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:59 Thread[客戶端窗口14,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:59 Thread[客戶端窗口7,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:59 Thread[客戶端窗口9,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:59 Thread[客戶端窗口12,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:59 Thread[客戶端窗口16,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:13:59 Thread[客戶端窗口17,5,main] 批量打印完成
2020-04-04 14:14:00 Thread[客戶端窗口6,5,main] 批量打印中
2020-04-04 14:14:00 Thread[客戶端窗口20,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:14:00 Thread[客戶端窗口6,5,main] 批量打印完成
2020-04-04 14:14:01 Thread[客戶端窗口8,5,main] 批量打印中
2020-04-04 14:14:01 Thread[客戶端窗口4,5,main]有客戶端正在批量打印中,請稍後再試!
2020-04-04 14:14:01 Thread[客戶端窗口8,5,main] 批量打印完成
2020-04-04 14:14:02 Thread[客戶端窗口1,5,main] 批量打印中
2020-04-04 14:14:02 Thread[客戶端窗口1,5,main] 批量打印完成
import jodd.datetime.JDateTime;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
public class MyThreed implements Runnable {
private final String URL = "http://……/get-batchlabelflag";
@Override
public void run() {
try {
HttpClient httpClient = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet(URL);
HttpResponse resultRep = httpClient.execute(httpGet);
String msg = EntityUtils.toString(resultRep.getEntity());
if ("true".equals(msg)) {
JDateTime jdt = new JDateTime();
System.out.println(jdt.toString("YYYY-MM-DD hh:mm:ss")+" "+Thread.currentThread().toString().replaceFirst(",5,main","") +" 有客戶端正在批量打印中,請稍後再試!");
} else {
// 有權限執行批量打印功能
// 模擬批量打印時間
JDateTime jdt = new JDateTime();
System.out.println(jdt.toString("YYYY-MM-DD hh:mm:ss") +" "+Thread.currentThread().toString().replaceFirst(",5,main","") + " 批量打印中");
Thread.sleep(3000);
HttpPut put = new HttpPut(URL);
httpClient.execute(put);
jdt = new JDateTime();
System.out.println(jdt.toString("YYYY-MM-DD hh:mm:ss") +" "+Thread.currentThread().toString().replaceFirst(",5,main","") + " 批量打印完成");
}
} catch (Exception e) {
}
}
}
public class ThreedTest {
public static void main(String[] args) {
//得到對象
MyThreed mtd = new MyThreed();
//把對象放入線程中
Thread t1 = new Thread(mtd, "客戶端01");
Thread t2 = new Thread(mtd, "客戶端02");
Thread t3 = new Thread(mtd, "客戶端03");
Thread t4 = new Thread(mtd, "客戶端04");
Thread t5 = new Thread(mtd, "客戶端05");
Thread t6 = new Thread(mtd, "客戶端06");
Thread t7 = new Thread(mtd, "客戶端07");
Thread t8 = new Thread(mtd, "客戶端08");
Thread t9 = new Thread(mtd, "客戶端09");
Thread t10 = new Thread(mtd, "客戶端10");
Thread t11 = new Thread(mtd, "客戶端11");
Thread t12 = new Thread(mtd, "客戶端12");
Thread t13 = new Thread(mtd, "客戶端13");
Thread t14 = new Thread(mtd, "客戶端14");
Thread t15 = new Thread(mtd, "客戶端15");
Thread t16 = new Thread(mtd, "客戶端16");
Thread t17 = new Thread(mtd, "客戶端17");
Thread t18 = new Thread(mtd, "客戶端18");
Thread t19 = new Thread(mtd, "客戶端19");
Thread t20 = new Thread(mtd, "客戶端20");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
t9.start();
t10.start();
t11.start();
t12.start();
t13.start();
t14.start();
t15.start();
t16.start();
t17.start();
t18.start();
t19.start();
t20.start();
}
}