中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

維恩圖在線制作網(wǎng)站站長工具的使用seo綜合查詢運(yùn)營

維恩圖在線制作網(wǎng)站,站長工具的使用seo綜合查詢運(yùn)營,做網(wǎng)站開發(fā)學(xué)什么內(nèi)容,可以用自己的電腦做網(wǎng)站主機(jī)FastThreadLocal 快在哪里 ? 引言FastThreadLocalset如何獲取當(dāng)前線程私有的InternalThreadLocalMap ?如何知道當(dāng)前線程使用到了哪些FastThreadLocal實(shí)例 ? get垃圾回收 小結(jié) 引言 FastThreadLocal 是 Netty 中造的一個(gè)輪子,那么為什么放著…

FastThreadLocal 快在哪里 ?

  • 引言
  • FastThreadLocal
    • set
      • 如何獲取當(dāng)前線程私有的InternalThreadLocalMap ?
      • 如何知道當(dāng)前線程使用到了哪些FastThreadLocal實(shí)例 ?
    • get
    • 垃圾回收
  • 小結(jié)


引言

FastThreadLocal 是 Netty 中造的一個(gè)輪子,那么為什么放著好端端的ThreadLocal不用,卻要重復(fù)造輪子呢?下面是Netty官方在源碼注釋中給出的解釋:

  • FastThreadLocal是ThreadLocal的一種特殊變體,當(dāng)從FastThreadLocalThread訪問時(shí)可以獲得更高的訪問性能。
  • 內(nèi)部FastThreadLocal使用數(shù)組中的常量索引來查找變量,而不是使用哈希碼和哈希表來查找。盡管看似非常微小,但與使用哈希表相比,它在性能上略有優(yōu)勢(shì),特別是在頻繁訪問時(shí)。

本文我們就來簡(jiǎn)單看看FastThreadLocal的具體實(shí)現(xiàn)。

在正式進(jìn)入實(shí)現(xiàn)解析之前,下面先給出FastThreadLocal使用示例:

    private static void fastThreadLocal() {final int MAX = 100000;long start = System.currentTimeMillis();// DefaultThreadFactory是Netty提供的實(shí)現(xiàn),用于創(chuàng)建類型為FastThreadLocalThread的線程DefaultThreadFactory defaultThreadFactory = new DefaultThreadFactory(FastThreadLocalTest.class);FastThreadLocal<String>[] fastThreadLocal = new FastThreadLocal[MAX];for (int i = 0; i < MAX; i++) {fastThreadLocal[i] = new FastThreadLocal<>();}// 測(cè)試單線程讀寫FastThreadLocal的耗時(shí)Thread thread = defaultThreadFactory.newThread(() -> {for (int i = 0; i < MAX; i++) {fastThreadLocal[i].set("java: " + i);}System.out.println("fastThreadLocal set: " + (System.currentTimeMillis() - start));for (int i = 0; i < MAX; i++) {for (int j = 0; j < MAX; j++) {fastThreadLocal[i].get();}}});thread.start();try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("fastThreadLocal total: " + (System.currentTimeMillis() - start));}

FastThreadLocal

在這里插入圖片描述
整體來看,FastThreadLocal的整體結(jié)構(gòu)和ThreadLocal是一致的,唯一的區(qū)別在于InternalThreadLocalMap 內(nèi)部存儲(chǔ)上,ThreadLocalMap 采用哈希定位實(shí)現(xiàn),而InternalThreadLocalMap 采用數(shù)組常量索引實(shí)現(xiàn),即:

  • 每個(gè)FastThreadLocal與一個(gè)固定的數(shù)字常量相關(guān)聯(lián)。

在這里插入圖片描述
FastThreadLocal內(nèi)部都會(huì)保存一個(gè)index下標(biāo),該下標(biāo)在FastThreadLocal實(shí)例初始化的時(shí)候被賦值:

public class FastThreadLocal<V> {// index 被final修飾,確保FastThreadLocal在InternalThreadLocalMap數(shù)組中的下標(biāo)是固定不變的private final int index;public FastThreadLocal() {// 計(jì)數(shù)器不斷遞增index = InternalThreadLocalMap.nextVariableIndex();}...
}    

還有一點(diǎn)也很重要,InternalThreadLocalMap內(nèi)部使用的桶數(shù)組沒有采用弱引用實(shí)現(xiàn),而是普通的強(qiáng)引用:

    // 1. InternalThreadLocalMap中桶數(shù)組的實(shí)現(xiàn)private Object[] indexedVariables;// 2. ThreadLocalMap中桶數(shù)組的實(shí)現(xiàn)static class Entry extends WeakReference<ThreadLocal<?>> {Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}private Entry[] table;

大家可以思考,InternalThreadLocalMap此處不使用弱引用實(shí)現(xiàn),是否存在內(nèi)存泄漏問題 ? 即當(dāng)用戶程序本身失去了對(duì)FastThreadLocal實(shí)例的強(qiáng)引用后,仍然被InternalThreadLocalMap強(qiáng)引用的FastThreadLocal如何被回收掉呢?

這里需要注意一點(diǎn): InternalThreadLocalMap與ThreadLocalMap沒有繼承關(guān)系
在這里插入圖片描述


set

當(dāng)我們通過FastThreadLocal的set方法設(shè)置值時(shí),其實(shí)和ThreadLocal一樣,還是向InternalThreadLocalMap中設(shè)置值:

    public final void set(V value) {// 1. UNSET 是空桶標(biāo)記-->等價(jià)于ThreadLocal中被垃圾回收后key為null的空Entry if (value != InternalThreadLocalMap.UNSET) {// 2. 獲取與當(dāng)前線程關(guān)聯(lián)的InternalThreadLocalMap// 以FastThreadLocal為key,value為val設(shè)置到InternalThreadLocalMap中    InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();setKnownNotUnset(threadLocalMap, value);} else {// 3. 當(dāng)設(shè)置的值為UNSET時(shí),表明需要清空當(dāng)前FastThreadLocalremove();}}

關(guān)于Set的整個(gè)流程,有兩點(diǎn)值得我們思考:

如何獲取當(dāng)前線程私有的InternalThreadLocalMap ?

如果我們當(dāng)前使用的線程類型為FastThreadLocalThread,那么可以直接獲取FastThreadLocalThread內(nèi)部持有的InternalThreadLocalMap:

public class FastThreadLocalThread extends Thread {...// 這一點(diǎn)和Thread內(nèi)部保存ThreadLocalMap實(shí)現(xiàn)一致private InternalThreadLocalMap threadLocalMap;...
}

如果我們當(dāng)前使用的線程類型是原始類型Thread,那么Netty這里會(huì)將InternalThreadLocalMap保存于當(dāng)前線程私有的ThreadLocal內(nèi)部:

public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {private static final ThreadLocal<InternalThreadLocalMap> slowThreadLocalMap =new ThreadLocal<InternalThreadLocalMap>();...
}            

上面兩種獲取方式,前一種被稱為fastGet,而后一種被稱為slowGet :

public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {public static InternalThreadLocalMap get() {Thread thread = Thread.currentThread();if (thread instanceof FastThreadLocalThread) {return fastGet((FastThreadLocalThread) thread);} else {return slowGet();}}// 1. 當(dāng)前線程類型為FastThreadLocalThread,則直接從獲取其內(nèi)部持有的InternalThreadLocalMap實(shí)例private static InternalThreadLocalMap fastGet(FastThreadLocalThread thread) {InternalThreadLocalMap threadLocalMap = thread.threadLocalMap();if (threadLocalMap == null) {thread.setThreadLocalMap(threadLocalMap = new InternalThreadLocalMap());}return threadLocalMap;}// 2. 當(dāng)前線程類型為傳統(tǒng)的Thread類型,則從當(dāng)前線程私有的ThreadLocal中獲取InternalThreadLocalMap實(shí)例 private static InternalThreadLocalMap slowGet() {InternalThreadLocalMap ret = slowThreadLocalMap.get();if (ret == null) {ret = new InternalThreadLocalMap();slowThreadLocalMap.set(ret);}return ret;}  ...
}  

如何知道當(dāng)前線程使用到了哪些FastThreadLocal實(shí)例 ?

為什么FastThreadLocal需要獲取到當(dāng)前線程使用到的所有FastThreadLocal實(shí)例呢?

上面說過,InternalThreadLocalMap本身沒有采用弱引用實(shí)現(xiàn),那么Netty就需要另想辦法回收掉失去了用戶程序強(qiáng)引用的FastThreadLocal,防止產(chǎn)生內(nèi)存泄漏。Netty此處采用的方式就是在FastThreadLocalRunnable包裝的Runnable對(duì)象任務(wù)執(zhí)行完畢后,清理掉當(dāng)前線程使用到的所有FastThreadLocal實(shí)現(xiàn)的:

final class FastThreadLocalRunnable implements Runnable {private final Runnable runnable;private FastThreadLocalRunnable(Runnable runnable) {this.runnable = ObjectUtil.checkNotNull(runnable, "runnable");}@Overridepublic void run() {try {runnable.run();} finally {FastThreadLocal.removeAll();}}static Runnable wrap(Runnable runnable) {return runnable instanceof FastThreadLocalRunnable ? runnable : new FastThreadLocalRunnable(runnable);}
}

那這里還是回歸第二個(gè)問題本身,即如何獲取當(dāng)前線程使用到的所有FastThreadLocal實(shí)例呢?

public class FastThreadLocal<V> {private void setKnownNotUnset(InternalThreadLocalMap threadLocalMap, V value) {// 1. 嘗試向threadLocalMap中設(shè)置值,如果是第一次設(shè)置,則記錄當(dāng)前線程使用到了當(dāng)前ThreadLocal// (直接常量值定位FastThreadLocal在ThreadLocalMap的哪個(gè)槽中) if (threadLocalMap.setIndexedVariable(index, value)) {// 2. 記錄當(dāng)前線程使用到了當(dāng)前FastThreadLocaladdToVariablesToRemove(threadLocalMap, this);}}private static void addToVariablesToRemove(InternalThreadLocalMap threadLocalMap, FastThreadLocal<?> variable) {// 1. variablesToRemoveIndex固定為0,threadLocalMap數(shù)組第一個(gè)槽位存放當(dāng)前線程使用到的FastThreadLocal集合Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);Set<FastThreadLocal<?>> variablesToRemove;// 2. 說明當(dāng)前FastThreadLocal是當(dāng)前線程第一個(gè)使用到的FastThreadLocal實(shí)例if (v == InternalThreadLocalMap.UNSET || v == null) {// 3. 準(zhǔn)備一個(gè)Set集合variablesToRemove = Collections.newSetFromMap(new IdentityHashMap<FastThreadLocal<?>, Boolean>());// 4. threadLocalMap中的0號(hào)槽位固定存放當(dāng)前線程使用到的FastThreadLocal實(shí)例threadLocalMap.setIndexedVariable(variablesToRemoveIndex, variablesToRemove);} else {variablesToRemove = (Set<FastThreadLocal<?>>) v;}// 5. 記錄當(dāng)前FastThreadLocal到集合中去variablesToRemove.add(variable);}...
}public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {public boolean setIndexedVariable(int index, Object value) {Object[] lookup = indexedVariables;// 1. 判斷InternalThreadLocalMap是否裝滿if (index < lookup.length) {Object oldValue = lookup[index];lookup[index] = value;// 2. 如果當(dāng)前槽位先前為空,說明是第一次使用到當(dāng)前FastThreadLocalreturn oldValue == UNSET;} else {// 3. 執(zhí)行擴(kuò)容,擴(kuò)容完畢后,在設(shè)置進(jìn)去 --> 說明當(dāng)前FastThreadLocal是第一次被使用expandIndexedVariableTableAndSet(index, value);return true;}}....
}    

當(dāng)前線程會(huì)在第一次使用到某個(gè)FastThreadLocal時(shí)進(jìn)行記錄,使用到的FastThreadLocal集合保存在InternalThreadLocalMap數(shù)組的0號(hào)槽位中:

public class FastThreadLocal<V> {// 當(dāng)FastThreadLocal類本身執(zhí)行初始化時(shí),該下標(biāo)就被初始化了,值默認(rèn)為0private static final int variablesToRemoveIndex = InternalThreadLocalMap.nextVariableIndex();...
}public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {// 這里的計(jì)數(shù)器也是全局共享的private static final AtomicInteger nextIndex = new AtomicInteger();...public static int nextVariableIndex() { // 每次獲取下標(biāo)時(shí),計(jì)數(shù)器累加一位int index = nextIndex.getAndIncrement();...return index;}
}    

在這里插入圖片描述
在這里插入圖片描述

set的整個(gè)流程中,我們也可以看出FastThreadLocal快就快在,可以根據(jù)當(dāng)前FastThreadLocal實(shí)例關(guān)聯(lián)的常量值直接定位其在InternalThreadLocalMap中的位置。


get

FastThreadLocal get的流程很簡(jiǎn)單,如下所示:

public class FastThreadLocal<V> {public final V get(InternalThreadLocalMap threadLocalMap) {// 1. 直接常量定位所在槽位Object v = threadLocalMap.indexedVariable(index);// 2. 如果當(dāng)前FastThreadLocal并非首次訪問,則直接對(duì)應(yīng)的值if (v != InternalThreadLocalMap.UNSET) {return (V) v;}// 3. 初始化FastThreadLocalreturn initialize(threadLocalMap);}private V initialize(InternalThreadLocalMap threadLocalMap) {V v = null;try {// 1. 調(diào)用回調(diào)進(jìn)行初始化v = initialValue();} catch (Exception e) {PlatformDependent.throwException(e);}// 2. 設(shè)置初始化的值threadLocalMap.setIndexedVariable(index, v);// 3. 注冊(cè)當(dāng)前FastThreadLocal,即記錄當(dāng)前線程使用了當(dāng)前FastThreadLocal實(shí)例addToVariablesToRemove(threadLocalMap, this);return v;}...
}    

垃圾回收

上面說過,InternalThreadLocalMap本身沒有采用弱引用實(shí)現(xiàn),那么Netty就需要另想辦法回收掉失去了用戶程序強(qiáng)引用的FastThreadLocal,防止產(chǎn)生內(nèi)存泄漏。Netty此處采用的方式就是在FastThreadLocalRunnable包裝的Runnable對(duì)象任務(wù)執(zhí)行完畢后,清理掉當(dāng)前線程使用到的所有FastThreadLocal實(shí)現(xiàn)的,這一點(diǎn)上面已經(jīng)提到過了,下面我們看看具體實(shí)現(xiàn)。

final class FastThreadLocalRunnable implements Runnable {private final Runnable runnable;private FastThreadLocalRunnable(Runnable runnable) {this.runnable = ObjectUtil.checkNotNull(runnable, "runnable");}@Overridepublic void run() {try {runnable.run();} finally {FastThreadLocal.removeAll();}}static Runnable wrap(Runnable runnable) {return runnable instanceof FastThreadLocalRunnable ? runnable : new FastThreadLocalRunnable(runnable);}
}

FastThreadLocal提供了一個(gè)靜態(tài)的removeAll方法,用于清除當(dāng)前線程使用到的所有FastThreadLocal實(shí)例:

public class FastThreadLocal<V> {... public static void removeAll() {// 1. 如果當(dāng)前線程沒有使用到FastThreadLocal,這里直接返回InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet();if (threadLocalMap == null) {return;}try {// 2. 獲取固定的0號(hào)槽位保存的Set集合,該集合內(nèi)保存了當(dāng)前線程使用到的所有FastThreadLocal實(shí)例集合 Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);if (v != null && v != InternalThreadLocalMap.UNSET) {Set<FastThreadLocal<?>> variablesToRemove = (Set<FastThreadLocal<?>>) v;// 3. 遍歷該集合內(nèi)每個(gè)FastThreadLocal實(shí)例,依次調(diào)用remove方法 FastThreadLocal<?>[] variablesToRemoveArray =variablesToRemove.toArray(new FastThreadLocal[0]);for (FastThreadLocal<?> tlv: variablesToRemoveArray) {tlv.remove(threadLocalMap);}}} finally {// 4. 置空threadlocalmapInternalThreadLocalMap.remove();}}
  1. 清空單個(gè)FastThreadLocal
public class FastThreadLocal<V> {public final void remove(InternalThreadLocalMap threadLocalMap) {if (threadLocalMap == null) {return;}// 1. 清除當(dāng)前FastThreadLocal占用的槽位Object v = threadLocalMap.removeIndexedVariable(index);// 2. 取消當(dāng)前FastThreadLocal的注冊(cè)removeFromVariablesToRemove(threadLocalMap, this);// 3. 執(zhí)行回調(diào)通知  if (v != InternalThreadLocalMap.UNSET) {try {onRemoval((V) v);} catch (Exception e) {PlatformDependent.throwException(e);}}}private static void removeFromVariablesToRemove(InternalThreadLocalMap threadLocalMap, FastThreadLocal<?> variable) {// 1. 獲取threadlocalmap的0號(hào)槽位保存的set集合  Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);...// 2. 從set集合中移除當(dāng)前fastThreadLocalSet<FastThreadLocal<?>> variablesToRemove = (Set<FastThreadLocal<?>>) v;variablesToRemove.remove(variable);}...
}public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {public Object removeIndexedVariable(int index) {Object[] lookup = indexedVariables;if (index < lookup.length) {Object v = lookup[index];// 將對(duì)應(yīng)槽位設(shè)置為UNSETlookup[index] = UNSET;return v;} else {return UNSET;}}...
}
  1. 置空ThreadLocalMap
public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {public static void remove() {Thread thread = Thread.currentThread();// 1. 如果threadLocalMap保存在FastThreadLocalThread內(nèi)部,則直接設(shè)置為nullif (thread instanceof FastThreadLocalThread) {((FastThreadLocalThread) thread).setThreadLocalMap(null);} else {// 2. 如果保存在當(dāng)前線程threadlocal中,則調(diào)用threadlocal的remove方法移除 slowThreadLocalMap.remove();}}...
} 

小結(jié)

FastThreadLocal為什么那么快,這個(gè)問題比較好回答:

  1. FastThreadLocal 內(nèi)部維護(hù)了一個(gè)索引常量 index,該常量在每次創(chuàng)建 FastThreadLocal 中都會(huì)自動(dòng)+1,從而保證了下標(biāo)的不重復(fù)性。
  2. 這要做雖然會(huì)產(chǎn)生大量的 index,但避免了在 ThreadLocal 中計(jì)算索引下標(biāo)位置以及處理 hash 沖突帶來的損耗,所以在操作數(shù)組時(shí)使用固定下標(biāo)要比使用計(jì)算哈希下標(biāo)有一定的性能優(yōu)勢(shì),特別是在頻繁使用時(shí)會(huì)非常顯著,用空間換時(shí)間,這就是高性能 Netty 的巧妙之處。
  3. 要利用 FastThreadLocal 帶來的性能優(yōu)勢(shì),就必須結(jié)合使用 FastThreadLocalThread 線程類或其子類,因?yàn)?FastThreadLocalThread 線程類會(huì)存儲(chǔ)必要的狀態(tài),如果使用了非 FastThreadLocalThread 線程類則會(huì)回到常規(guī) ThreadLocal。

下面給出一個(gè)測(cè)試用例,來看看FastThreadLocal和ThreadLocal在性能上的差異:

public class FastThreadLocalTest {public static void main(String[] args) {new Thread(FastThreadLocalTest::threadLocal).start();new Thread(FastThreadLocalTest::fastThreadLocal).start();}private static void fastThreadLocal() {final int MAX = 100000;long start = System.currentTimeMillis();// DefaultThreadFactory是Netty提供的實(shí)現(xiàn),用于創(chuàng)建類型為FastThreadLocalThread的線程DefaultThreadFactory defaultThreadFactory = new DefaultThreadFactory(FastThreadLocalTest.class);FastThreadLocal<String>[] fastThreadLocal = new FastThreadLocal[MAX];for (int i = 0; i < MAX; i++) {fastThreadLocal[i] = new FastThreadLocal<>();}// 測(cè)試單線程讀寫FastThreadLocal的耗時(shí)Thread thread = defaultThreadFactory.newThread(() -> {for (int i = 0; i < MAX; i++) {fastThreadLocal[i].set("java: " + i);}System.out.println("fastThreadLocal set: " + (System.currentTimeMillis() - start));for (int i = 0; i < MAX; i++) {for (int j = 0; j < MAX; j++) {fastThreadLocal[i].get();}}});thread.start();try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("fastThreadLocal total: " + (System.currentTimeMillis() - start));}private static void threadLocal() {final int MAX = 100000;long start = System.currentTimeMillis();ThreadLocal<String>[] threadLocals = new ThreadLocal[MAX];for (int i = 0; i < MAX; i++) {threadLocals[i] = new ThreadLocal<>();}Thread thread = new Thread(() -> {for (int i = 0; i < MAX; i++) {threadLocals[i].set("java: " + i);}System.out.println("threadLocal set: " + (System.currentTimeMillis() - start));for (int i = 0; i < MAX; i++) {for (int j = 0; j < MAX; j++) {threadLocals[i].get();}}});thread.start();try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("threadLocal total: " + (System.currentTimeMillis() - start));}}

在這里插入圖片描述
在大量讀寫面前,寫操作的效率差不多,但讀操作 FastThreadLocal 比 ThreadLocal 快的不是一個(gè)數(shù)量級(jí),簡(jiǎn)直是秒殺 ThreadLocal 的存在。

當(dāng)我們把max的值縮小為1000時(shí),此時(shí)讀寫操作不多時(shí),ThreadLocal 明顯更勝一籌!
在這里插入圖片描述
Netty 中的 FastThreadLocal 在大量頻繁讀寫操作時(shí)效率要高于 ThreadLocal,但要注意結(jié)合 Netty 自帶的線程類使用。

如果沒有大量頻繁讀寫操作的場(chǎng)景,JDK 自帶的 ThreadLocal 足矣,并且性能還要優(yōu)于 FastThreadLocal。

http://www.risenshineclean.com/news/11325.html

相關(guān)文章:

  • 做網(wǎng)站不用服務(wù)器嗎鄭州網(wǎng)站開發(fā)公司
  • 找做報(bào)紙的背景圖去什么網(wǎng)站海外推廣代理商
  • 個(gè)人如何開網(wǎng)站東莞網(wǎng)絡(luò)推廣營銷
  • 哪家網(wǎng)站建設(shè)服務(wù)好開發(fā)網(wǎng)站需要多少錢
  • 懷化市優(yōu)化辦電話seo快速排名優(yōu)化公司
  • 東莞建工集團(tuán)知乎推廣優(yōu)化
  • 周口網(wǎng)站制作公司哪家好快速網(wǎng)站seo效果
  • 江蘇 網(wǎng)站 備案黃頁引流推廣網(wǎng)站入口
  • 網(wǎng)絡(luò)搏彩網(wǎng)站做代理衡水seo營銷
  • 做網(wǎng)站用的系統(tǒng)公司網(wǎng)絡(luò)推廣營銷
  • 網(wǎng)站主機(jī)是服務(wù)器嗎深圳廣告公司
  • 我的網(wǎng)站沒備案怎么做淘寶客推廣小程序運(yùn)營推廣公司
  • 服裝網(wǎng)站建設(shè)公司地址國際新聞最新消息今天軍事新聞
  • 黑龍江住房和建設(shè)廳網(wǎng)站寧波seo網(wǎng)絡(luò)推廣推薦
  • 做網(wǎng)站模板的海報(bào)尺寸多少錢電商seo優(yōu)化是什么意思
  • 做網(wǎng)站必須要電腦嗎app開發(fā)工具
  • 公司網(wǎng)站建立教程aso優(yōu)化平臺(tái)有哪些
  • 重慶建站模板源碼推動(dòng)防控措施持續(xù)優(yōu)化
  • 用淘寶評(píng)論做網(wǎng)站個(gè)人博客網(wǎng)頁制作
  • 北京國家建設(shè)部網(wǎng)站首頁上海百度推廣電話
  • 購買云服務(wù)器后怎么做網(wǎng)站seo優(yōu)化幾個(gè)關(guān)鍵詞
  • 建設(shè)大型網(wǎng)站世界足球排名前100名
  • wordpress做論壇網(wǎng)站免費(fèi)推廣網(wǎng)站排行榜
  • 靜態(tài)網(wǎng)站可以做哪些內(nèi)容小程序開發(fā)框架
  • 免費(fèi)下載ppt模板的網(wǎng)站有哪些站長工具seo源碼
  • 做交易網(wǎng)站百度seo排名如何提升
  • 溫州網(wǎng)站建設(shè)前十公司大同優(yōu)化推廣
  • 美圖秀秀可以做網(wǎng)站嗎河南省網(wǎng)站
  • 加強(qiáng)網(wǎng)站政務(wù)服務(wù)建設(shè)百度指數(shù)使用方法
  • 印刷網(wǎng)站建設(shè) 優(yōu)幫云品牌運(yùn)營