public class SmoothServer { public SmoothServer(String ip, int weight, int curWeight) { this.ip = ip; this.weight = weight; this.curWeight = curWeight; } private String ip; private int weight; private int curWeight; public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public int getCurWeight() { return curWeight; } public void setCurWeight(int curWeight) { this.curWeight = curWeight; } }
public class SmoothWeightRoundRobin { /**初始化全部的服務器**/ List<SmoothServer> servers = new ArrayList<>(); /**服務器權重總和*/ private int weightCount; public void init(List<SmoothServer> servers) { this.servers = servers; this.weightCount = this.servers.stream().map(server -> server.getWeight()).reduce(0, (l, r) -> l + r); } /**獲取須要執行的服務器**/ public SmoothServer getServer() { SmoothServer tmpSv = null; for (SmoothServer sv : servers) { sv.setCurWeight(sv.getWeight() + sv.getCurWeight()); if (tmpSv == null || tmpSv.getCurWeight() < sv.getCurWeight()) tmpSv = sv; } tmpSv.setCurWeight(tmpSv.getCurWeight() - weightCount); return tmpSv; } }
public class RobinExecute { /** 線程使用完不會清除該變量,會一直保留着,因爲線程 池化因此不用擔憂內存泄漏 **/ private ThreadLocal<SmoothWeightRoundRobin> weightRoundRobinTl = new ThreadLocal<SmoothWeightRoundRobin>(); private ReentrantLock lock = new ReentrantLock(); /** 爲何添加volatile,是由於 ReentrantLock 並不保證內存可見性 **/ private volatile SmoothWeightRoundRobin smoothWeightRoundRobin; public static void main(String[] args) { RobinExecute robinExecute = new RobinExecute(); /** ================== TheadLocal ========================**/ robinExecute.acquireWeightRoundRobinOfTheadLocal().getServer(); /** ================== ReentrantLock 可重入鎖 ========================**/ robinExecute.getLock().lock(); //notice: 注意此鎖會無休止的等待資源,若是使用此鎖,無比保證資源可以被拿到 try { robinExecute.acquireWeightRoundRobinOfLock(); } catch (Exception e) { e.printStackTrace(); } finally { //確保必定要釋放鎖 robinExecute.getLock().unlock(); } } /** * 在分佈式狀況,第二種使用方式 使用cas ReentrantLock 可重入鎖 * notice: * @return */ public SmoothServer acquireWeightRoundRobinOfLock() { if (smoothWeightRoundRobin == null) { SmoothWeightRoundRobin weightRoundRobin = new SmoothWeightRoundRobin(); List<SmoothServer> servers = new ArrayList<>(); servers.add(new SmoothServer("191", 1, 0)); servers.add(new SmoothServer("192", 2, 0)); servers.add(new SmoothServer("194", 4, 0)); weightRoundRobin.init(servers); smoothWeightRoundRobin = weightRoundRobin; } return smoothWeightRoundRobin.getServer(); } /** * 在分佈式狀況,第一種使用方式 ThreadLock * notice: 只有在使用池化技術的狀況才建議使用此方式,不然達不到效果,還會形成內存泄漏 * @return */ public SmoothWeightRoundRobin acquireWeightRoundRobinOfTheadLocal() { return Optional.ofNullable(weightRoundRobinTl.get()) .orElseGet(() -> { SmoothWeightRoundRobin weightRoundRobin = new SmoothWeightRoundRobin(); List<SmoothServer> servers = new ArrayList<>(); servers.add(new SmoothServer("191", 1, 0)); servers.add(new SmoothServer("192", 2, 0)); servers.add(new SmoothServer("194", 4, 0)); weightRoundRobin.init(servers); weightRoundRobinTl.set(weightRoundRobin); return weightRoundRobin; }); } public ReentrantLock getLock() { return lock; } public ThreadLocal<SmoothWeightRoundRobin> getWeightRoundRobinTl() { return weightRoundRobinTl; } }