Java基礎(chǔ)16:Java多線(xiàn)程基礎(chǔ)最全總結(jié)

更多內(nèi)容請(qǐng)關(guān)注微信公眾號(hào)【Java技術(shù)江湖】

創(chuàng)新互聯(lián)公司,為您提供網(wǎng)站建設(shè)公司、成都網(wǎng)站制作、網(wǎng)站營(yíng)銷(xiāo)推廣、網(wǎng)站開(kāi)發(fā)設(shè)計(jì),對(duì)服務(wù)成都垃圾桶等多個(gè)行業(yè)擁有豐富的網(wǎng)站建設(shè)及推廣經(jīng)驗(yàn)。創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)公司成立于2013年,提供專(zhuān)業(yè)網(wǎng)站制作報(bào)價(jià)服務(wù),我們深知市場(chǎng)的競(jìng)爭(zhēng)激烈,認(rèn)真對(duì)待每位客戶(hù),為客戶(hù)提供賞心悅目的作品。 與客戶(hù)共同發(fā)展進(jìn)步,是我們永遠(yuǎn)的責(zé)任!

這是一位阿里 Java 工程師的技術(shù)小站,作者黃小斜,專(zhuān)注 Java 相關(guān)技術(shù):SSM、SpringBoot、MySQL、分布式、中間件、集群、Linux、網(wǎng)絡(luò)、多線(xiàn)程,偶爾講點(diǎn)Docker、ELK,同時(shí)也分享技術(shù)干貨和學(xué)習(xí)經(jīng)驗(yàn),致力于Java全棧開(kāi)發(fā)!(關(guān)注公眾號(hào)后回復(fù)”資料“即可領(lǐng)取 3T 免費(fèi)技術(shù)學(xué)習(xí)資源以及我我原創(chuàng)的程序員校招指南、Java學(xué)習(xí)指南等資源)

Java基礎(chǔ)16:Java多線(xiàn)程基礎(chǔ)最全總結(jié)cdn.xitu.io/2019/4/6/169f1735fd0d1d16?w=900&h=500&f=jpeg&s=109856">

本文介紹了Java多線(xiàn)程的基本概念,使用方法,以及底層實(shí)現(xiàn)原理。幫助你更好地使用Java的多線(xiàn)程。

具體代碼在我的GitHub中可以找到

https://github.com/h3pl/MyTech

喜歡的話(huà)麻煩點(diǎn)一下星哈謝謝。

文章首發(fā)于我的個(gè)人博客:

https://h3pl.github.io/2018/05/04/javase16

更多關(guān)于Java后端學(xué)習(xí)的內(nèi)容請(qǐng)到我的CSDN博客上查看:

https://blog.csdn.net/a724888

Java中的線(xiàn)程

Java之父對(duì)線(xiàn)程的定義是:

線(xiàn)程是一個(gè)獨(dú)立執(zhí)行的調(diào)用序列,同一個(gè)進(jìn)程的線(xiàn)程在同一時(shí)刻共享一些系統(tǒng)資源(比如文件句柄等)也能訪(fǎng)問(wèn)同一個(gè)進(jìn)程所創(chuàng)建的對(duì)象資源(內(nèi)存資源)。java.lang.Thread對(duì)象負(fù)責(zé)統(tǒng)計(jì)和控制這種行為。

每個(gè)程序都至少擁有一個(gè)線(xiàn)程-即作為Java虛擬機(jī)(JVM)啟動(dòng)參數(shù)運(yùn)行在主類(lèi)main方法的線(xiàn)程。在Java虛擬機(jī)初始化過(guò)程中也可能啟動(dòng)其他的后臺(tái)線(xiàn)程。這種線(xiàn)程的數(shù)目和種類(lèi)因JVM的實(shí)現(xiàn)而異。然而所有用戶(hù)級(jí)線(xiàn)程都是顯式被構(gòu)造并在主線(xiàn)程或者是其他用戶(hù)線(xiàn)程中被啟動(dòng)。

  本文主要講了java中多線(xiàn)程的使用方法、線(xiàn)程同步、線(xiàn)程數(shù)據(jù)傳遞、線(xiàn)程狀態(tài)及相應(yīng)的一些線(xiàn)程函數(shù)用法、概述等。在這之前,首先讓我們來(lái)了解下在操作系統(tǒng)中進(jìn)程和線(xiàn)程的區(qū)別:
  進(jìn)程:每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(進(jìn)程上下文),進(jìn)程間的切換會(huì)有較大的開(kāi)銷(xiāo),一個(gè)進(jìn)程包含1--n個(gè)線(xiàn)程。(進(jìn)程是資源分配的最小單位)
  線(xiàn)程:同一類(lèi)線(xiàn)程共享代碼和數(shù)據(jù)空間,每個(gè)線(xiàn)程有獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器(PC),線(xiàn)程切換開(kāi)銷(xiāo)小。(線(xiàn)程是cpu調(diào)度的最小單位)
  線(xiàn)程和進(jìn)程一樣分為五個(gè)階段:創(chuàng)建、就緒、運(yùn)行、阻塞、終止。
  多進(jìn)程是指操作系統(tǒng)能同時(shí)運(yùn)行多個(gè)任務(wù)(程序)。
  多線(xiàn)程是指在同一程序中有多個(gè)順序流在執(zhí)行。
在java中要想實(shí)現(xiàn)多線(xiàn)程,有兩種手段,一種是繼續(xù)Thread類(lèi),另外一種是實(shí)現(xiàn)Runable接口.(其實(shí)準(zhǔn)確來(lái)講,應(yīng)該有三種,還有一種是實(shí)現(xiàn)Callable接口,并與Future、線(xiàn)程池結(jié)合使用

Java線(xiàn)程內(nèi)存模型

下面的圖大致介紹了Java線(xiàn)程的調(diào)用過(guò)程,每個(gè)線(xiàn)程使用一個(gè)獨(dú)立的調(diào)用棧進(jìn)行線(xiàn)程執(zhí)行,棧中的數(shù)據(jù)不共享,堆區(qū)和方法區(qū)的數(shù)據(jù)是共享的。

Java基礎(chǔ)16:Java多線(xiàn)程基礎(chǔ)最全總結(jié)

Java基礎(chǔ)16:Java多線(xiàn)程基礎(chǔ)最全總結(jié)

Java基礎(chǔ)16:Java多線(xiàn)程基礎(chǔ)最全總結(jié)

構(gòu)造方法和守護(hù)線(xiàn)程

構(gòu)造方法
Thread類(lèi)中不同的構(gòu)造方法接受如下參數(shù)的不同組合:
一個(gè)Runnable對(duì)象,這種情況下,Thread.start方法將會(huì)調(diào)用對(duì)應(yīng)Runnable對(duì)象的run方法。如果沒(méi)有提供Runnable對(duì)象,那么就會(huì)立即得到一個(gè)Thread.run的默認(rèn)實(shí)現(xiàn)。
一個(gè)作為線(xiàn)程標(biāo)識(shí)名的String字符串,該標(biāo)識(shí)在跟蹤和調(diào)試過(guò)程中會(huì)非常有用,除此別無(wú)它用。
線(xiàn)程組(ThreadGroup),用來(lái)放置新創(chuàng)建的線(xiàn)程,如果提供的ThreadGroup不允許被訪(fǎng)問(wèn),那么就會(huì)拋出一個(gè)SecurityException 。
Thread對(duì)象擁有一個(gè)守護(hù)(daemon)標(biāo)識(shí)屬性,這個(gè)屬性無(wú)法在構(gòu)造方法中被賦值,但是可以在線(xiàn)程啟動(dòng)之前設(shè)置該屬性(通過(guò)setDaemon方法)。
當(dāng)程序中所有的非守護(hù)線(xiàn)程都已經(jīng)終止,調(diào)用setDaemon方法可能會(huì)導(dǎo)致虛擬機(jī)粗暴的終止線(xiàn)程并退出。
isDaemon方法能夠返回該屬性的值。守護(hù)狀態(tài)的作用非常有限,即使是后臺(tái)線(xiàn)程在程序退出的時(shí)候也經(jīng)常需要做一些清理工作。
(daemon的發(fā)音為”day-mon”,這是系統(tǒng)編程傳統(tǒng)的遺留,系統(tǒng)守護(hù)進(jìn)程是一個(gè)持續(xù)運(yùn)行的進(jìn)程,比如打印機(jī)隊(duì)列管理,它總是在系統(tǒng)中運(yùn)行。)

啟動(dòng)線(xiàn)程的方式和isAlive方法

啟動(dòng)線(xiàn)程 調(diào)用start方法會(huì)觸發(fā)Thread實(shí)例以一個(gè)新的線(xiàn)程啟動(dòng)其run方法。新線(xiàn)程不會(huì)持有調(diào)用線(xiàn)程的任何同步鎖。

當(dāng)一個(gè)線(xiàn)程正常地運(yùn)行結(jié)束或者拋出某種未檢測(cè)的異常(比如,運(yùn)行時(shí)異常(RuntimeException),錯(cuò)誤(ERROR) 或者其子類(lèi))線(xiàn)程就會(huì)終止。

當(dāng)線(xiàn)程終止之后,是不能被重新啟動(dòng)的。在同一個(gè)Thread上調(diào)用多次start方法會(huì)拋出InvalidThreadStateException異常。

如果線(xiàn)程已經(jīng)啟動(dòng)但是還沒(méi)有終止,那么調(diào)用isAlive方法就會(huì)返回true.即使線(xiàn)程由于某些原因處于阻塞(Blocked)狀態(tài)該方法依然返回true。

如果線(xiàn)程已經(jīng)被取消(cancelled),那么調(diào)用其isAlive在什么時(shí)候返回false就因各Java虛擬機(jī)的實(shí)現(xiàn)而異了。沒(méi)有方法可以得知一個(gè)處于非活動(dòng)狀態(tài)的線(xiàn)程是否已經(jīng)被啟動(dòng)過(guò)了。

優(yōu)先級(jí)

Java的線(xiàn)程實(shí)現(xiàn)基本上都是內(nèi)核級(jí)線(xiàn)程的實(shí)現(xiàn),所以Java線(xiàn)程的具體執(zhí)行還取決于操作系統(tǒng)的特性。

Java虛擬機(jī)為了實(shí)現(xiàn)跨平臺(tái)(不同的硬件平臺(tái)和各種操作系統(tǒng))的特性,Java語(yǔ)言在線(xiàn)程調(diào)度與調(diào)度公平性上未作出任何的承諾,甚至都不會(huì)嚴(yán)格保證線(xiàn)程會(huì)被執(zhí)行。但是Java線(xiàn)程卻支持優(yōu)先級(jí)的方法,這些方法會(huì)影響線(xiàn)程的調(diào)度:

每個(gè)線(xiàn)程都有一個(gè)優(yōu)先級(jí),分布在Thread.MIN_PRIORITY和Thread.MAX_PRIORITY之間(分別為1和10) 默認(rèn)情況下,新創(chuàng)建的線(xiàn)程都擁有和創(chuàng)建它的線(xiàn)程相同的優(yōu)先級(jí)。main方法所關(guān)聯(lián)的初始化線(xiàn)程擁有一個(gè)默認(rèn)的優(yōu)先級(jí),這個(gè)優(yōu)先級(jí)是Thread.NORM_PRIORITY (5).

線(xiàn)程的當(dāng)前優(yōu)先級(jí)可以通過(guò)getPriority方法獲得。 線(xiàn)程的優(yōu)先級(jí)可以通過(guò)setPriority方法來(lái)動(dòng)態(tài)的修改,一個(gè)線(xiàn)程的最高優(yōu)先級(jí)由其所在的線(xiàn)程組限定。

線(xiàn)程的控制方法

只有很少幾個(gè)方法可以用于跨線(xiàn)程交流:

每個(gè)線(xiàn)程都有一個(gè)相關(guān)的Boolean類(lèi)型的中斷標(biāo)識(shí)。在線(xiàn)程t上調(diào)用t.interrupt會(huì)將該線(xiàn)程的中斷標(biāo)識(shí)設(shè)為true,除非線(xiàn)程t正處于Object.wait,Thread.sleep,或者Thread.join,這些情況下interrupt調(diào)用會(huì)導(dǎo)致t上的這些操作拋出InterruptedException異常,但是t的中斷標(biāo)識(shí)會(huì)被設(shè)為false。
任何一個(gè)線(xiàn)程的中斷狀態(tài)都可以通過(guò)調(diào)用isInterrupted方法來(lái)得到。如果線(xiàn)程已經(jīng)通過(guò)interrupt方法被中斷,這個(gè)方法將會(huì)返回true。
但是如果調(diào)用了Thread.interrupted方法且中斷標(biāo)識(shí)還沒(méi)有被重置,或者是線(xiàn)程處于wait,sleep,join過(guò)程中,調(diào)用isInterrupted方法將會(huì)拋出InterruptedException異常。
調(diào)用t.join()方法將會(huì)暫停執(zhí)行調(diào)用線(xiàn)程,直到線(xiàn)程t執(zhí)行完畢:當(dāng)t.isAlive()方法返回false的時(shí)候調(diào)用t.join()將會(huì)直接返回(return)。
另一個(gè)帶參數(shù)毫秒(millisecond)的join方法在被調(diào)用時(shí),如果線(xiàn)程沒(méi)能夠在指定的時(shí)間內(nèi)完成,調(diào)用線(xiàn)程將重新得到控制權(quán)。
因?yàn)閕sAlive方法的實(shí)現(xiàn)原理,所以在一個(gè)還沒(méi)有啟動(dòng)的線(xiàn)程上調(diào)用join方法是沒(méi)有任何意義的。同樣的,試圖在一個(gè)還沒(méi)有創(chuàng)建的線(xiàn)程上調(diào)用join方法也是不明智的。
起初,Thread類(lèi)還支持一些另外一些控制方法:suspend,resume,stop以及destroy。這幾個(gè)方法已經(jīng)被聲明過(guò)期。其中destroy方法從來(lái)沒(méi)有被實(shí)現(xiàn),估計(jì)以后也不會(huì)。而通過(guò)使用等待/喚醒機(jī)制增加suspend和resume方法在安全性和可靠性的效果有所欠缺

Thread的靜態(tài)方法

靜態(tài)方法
Thread類(lèi)中的部分方法被設(shè)計(jì)為只適用于當(dāng)前正在運(yùn)行的線(xiàn)程(即調(diào)用Thread方法的線(xiàn)程)。為強(qiáng)調(diào)這點(diǎn),這些方法都被聲明為靜態(tài)的。
Thread.currentThread方法會(huì)返回當(dāng)前線(xiàn)程的引用,得到這個(gè)引用可以用來(lái)調(diào)用其他的非靜態(tài)方法,比如Thread.currentThread().getPriority()會(huì)返回調(diào)用線(xiàn)程的優(yōu)先級(jí)。
Thread.interrupted方法會(huì)清除當(dāng)前線(xiàn)程的中斷狀態(tài)并返回前一個(gè)狀態(tài)。(一個(gè)線(xiàn)程的中斷狀態(tài)是不允許被其他線(xiàn)程清除的)
Thread.sleep(long msecs)方法會(huì)使得當(dāng)前線(xiàn)程暫停執(zhí)行至少msecs毫秒。
Thread.yield方法純粹只是建議Java虛擬機(jī)對(duì)其他已經(jīng)處于就緒狀態(tài)的線(xiàn)程(如果有的話(huà))調(diào)度執(zhí)行,而不是當(dāng)前線(xiàn)程。最終Java虛擬機(jī)如何去實(shí)現(xiàn)這種行為就完全看其喜好了。

線(xiàn)程組

每一個(gè)線(xiàn)程都是一個(gè)線(xiàn)程組中的成員。默認(rèn)情況下,新建線(xiàn)程和創(chuàng)建它的線(xiàn)程屬于同一個(gè)線(xiàn)程組。線(xiàn)程組是以樹(shù)狀分布的。
當(dāng)創(chuàng)建一個(gè)新的線(xiàn)程組,這個(gè)線(xiàn)程組成為當(dāng)前線(xiàn)程組的子組。getThreadGroup方法會(huì)返回當(dāng)前線(xiàn)程所屬的線(xiàn)程組,對(duì)應(yīng)地,ThreadGroup類(lèi)也有方法可以得到哪些線(xiàn)程目前屬于這個(gè)線(xiàn)程組,比如enumerate方法。
ThreadGroup類(lèi)存在的一個(gè)目的是支持安全策略來(lái)動(dòng)態(tài)的限制對(duì)該組的線(xiàn)程操作。比如對(duì)不屬于同一組的線(xiàn)程調(diào)用interrupt是不合法的。
這是為避免某些問(wèn)題(比如,一個(gè)applet線(xiàn)程嘗試殺掉主屏幕的刷新線(xiàn)程)所采取的措施。ThreadGroup也可以為該組所有線(xiàn)程設(shè)置一個(gè)最大的線(xiàn)程優(yōu)先級(jí)。
線(xiàn)程組往往不會(huì)直接在程序中被使用。在大多數(shù)的應(yīng)用中,如果僅僅是為在程序中跟蹤線(xiàn)程對(duì)象的分組,那么普通的集合類(lèi)(比如java.util.Vector)應(yīng)是更好的選擇。

多線(xiàn)程的實(shí)現(xiàn)

public class 多線(xiàn)程實(shí)例 {
    //繼承thread
    @Test
    public void test1() {
        class A extends Thread {
            @Override
            public void run() {
                System.out.println("A run");
            }
        }
        A a = new A();
        a.start();
    }
    //實(shí)現(xiàn)Runnable
    @Test
    public void test2() {
        class B implements Runnable {
            @Override
            public void run() {
                System.out.println("B run");
            }
        }
        B b = new B();
        //Runable實(shí)現(xiàn)類(lèi)需要由Thread類(lèi)包裝后才能執(zhí)行
        new Thread(b).start();
    }
    //有返回值的線(xiàn)程
    @Test
    public void test3() {
        Callable callable = new Callable() {
            int sum = 0;
            @Override
            public Object call() throws Exception {
                for (int i = 0;i < 5;i ++) {
                    sum += i;
                }
                return sum;
            }
        };
        //這里要用FutureTask,否則不能加入Thread構(gòu)造方法
        FutureTask futureTask = new FutureTask(callable);
        new Thread(futureTask).start();
        try {
            System.out.println(futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
    //線(xiàn)程池實(shí)現(xiàn)
    @Test
    public void test4() {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        //execute直接執(zhí)行線(xiàn)程
        executorService.execute(new Thread());
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable");
            }
        });
        //submit提交有返回結(jié)果的任務(wù),運(yùn)行完后返回結(jié)果。
        Future future = executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "a";
            }
        });
        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        ArrayList<String> list = new ArrayList<>();
        //有返回值的線(xiàn)程組將返回值存進(jìn)集合
        for (int i = 0;i < 5;i ++ ) {
            int finalI = i;
            Future future1 = executorService.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return "res" + finalI;
                }
            });
            try {
                list.add((String) future1.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        for (String s : list) {
            System.out.println(s);
        }
    }
}

線(xiàn)程狀態(tài)轉(zhuǎn)換

public class 線(xiàn)程的狀態(tài)轉(zhuǎn)換 {
//一開(kāi)始線(xiàn)程是init狀態(tài),結(jié)束時(shí)是terminated狀態(tài)
class t implements Runnable {
    private String name;
    public t(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        System.out.println(name + "run");
    }
}
//測(cè)試join,父線(xiàn)程在子線(xiàn)程運(yùn)行時(shí)進(jìn)入waiting狀態(tài)
@Test
public void test1() throws InterruptedException {
    Thread dad = new Thread(new Runnable() {
        Thread son = new Thread(new t("son"));
        @Override
        public void run() {
            System.out.println("dad init");
            son.start();
            try {
                //保證子線(xiàn)程運(yùn)行完再運(yùn)行父線(xiàn)程
                son.join();
                System.out.println("dad run");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    //調(diào)用start,線(xiàn)程進(jìn)入runnable狀態(tài),等待系統(tǒng)調(diào)度
    dad.start();
    //在父線(xiàn)程中對(duì)子線(xiàn)程實(shí)例使用join,保證子線(xiàn)程在父線(xiàn)程之前執(zhí)行完
}
//測(cè)試sleep
@Test
public void test2(){
    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("t1 run");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    //主線(xiàn)程休眠。進(jìn)入time waiting狀態(tài)
    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    t1.start();
}
//線(xiàn)程2進(jìn)入blocked狀態(tài)。
public static void main(String[] args) {
    test4();
    Thread.yield();//進(jìn)入runnable狀態(tài)
}
//測(cè)試blocked狀態(tài)
public static void test4() {
    class A {
        //線(xiàn)程1獲得實(shí)例鎖以后線(xiàn)程2無(wú)法獲得實(shí)例鎖,所以進(jìn)入blocked狀態(tài)
        synchronized void run() {
            while (true) {
                System.out.println("run");
            }
        }
    }
    A a = new A();
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("t1 get lock");
            a.run();
        }
    }).start();
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("t2 get lock");
            a.run();
        }
    }).start();
}
//volatile保證線(xiàn)程可見(jiàn)性
volatile static int flag = 1;
//object作為鎖對(duì)象,用于線(xiàn)程使用wait和notify方法
volatile static Object o = new Object();
//測(cè)試wait和notify
//wait后進(jìn)入waiting狀態(tài),被notify進(jìn)入blocked(阻塞等待鎖釋放)或者runnable狀態(tài)(獲取到鎖)
public void test5() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            //wait和notify只能在同步代碼塊內(nèi)使用
            synchronized (o) {
                while (true) {
                    if (flag == 0) {
                        try {
                            Thread.sleep(2000);
                            System.out.println("thread1 wait");
                            //釋放鎖,線(xiàn)程掛起進(jìn)入object的等待隊(duì)列,后續(xù)代碼運(yùn)行
                            o.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("thread1 run");
                    System.out.println("notify t2");
                    flag = 0;
                    //通知等待隊(duì)列的一個(gè)線(xiàn)程獲取鎖
                    o.notify();
                }
            }
        }
    }).start();
    //解釋同上
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                synchronized (o) {
                    if (flag == 1) {
                        try {
                            Thread.sleep(2000);
                            System.out.println("thread2 wait");
                            o.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("thread2 run");
                    System.out.println("notify t1");
                    flag = 1;
                    o.notify();
                }
            }
        }
    }).start();
}
//輸出結(jié)果是
//    thread1 run
//    notify t2
//    thread1 wait
//    thread2 run
//    notify t1
//    thread2 wait
//    thread1 run
//    notify t2
//不斷循環(huán)
}

當(dāng)前名稱(chēng):Java基礎(chǔ)16:Java多線(xiàn)程基礎(chǔ)最全總結(jié)
標(biāo)題路徑:http://bm7419.com/article18/jceidp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、服務(wù)器托管、網(wǎng)站制作、品牌網(wǎng)站設(shè)計(jì)、Google網(wǎng)站排名

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)