本篇內(nèi)容主要講解“java多線程機制是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“java多線程機制是什么”吧!
10年的亞東網(wǎng)站建設經(jīng)驗,針對設計、前端、開發(fā)、售后、文案、推廣等六對一服務,響應快,48小時及時工作處理。全網(wǎng)整合營銷推廣的優(yōu)勢是能夠根據(jù)用戶設備顯示端的尺寸不同,自動調(diào)整亞東建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)從事“亞東網(wǎng)站設計”,“亞東網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。
程序(program):是為完成特定任務、用某種語言編寫的一組指令的集合,是一段靜態(tài)的代碼。 (程序是靜態(tài)的)
進程(process):是程序的一次執(zhí)行過程,正在運行的一個程序,進程作為資源分配的單位,在內(nèi)存中會為每個進程分配不同的內(nèi)存區(qū)域。 (進程是動態(tài)的)是一個動的過程 ,進程的生命周期 : 有它自身的產(chǎn)生、存在和消亡的過程
目前操作系統(tǒng)都是支持多進程,可以同時執(zhí)行多個進程,通過進程ID區(qū)分
線程(thread):進程中的一條執(zhí)行路徑,也是CUP的基本調(diào)度單位,一個進程由一個或多個線程組成,彼此間完成不同的工作,多個線程同時執(zhí)行,稱為多線程。
線程的組成
任何一個線程都具有的基本組成部分:
CPU時間片:操作系統(tǒng)(OS)會為每一個線程分配執(zhí)行時間。
運行數(shù)據(jù):堆空間(存儲線程需要使用的對象,多個線程可以共享堆中的對象);棧空間(存儲線程需要使用的局部變量,每個線程都擁有獨立的棧)
線程的特點
線程搶占式執(zhí)行(效率高、可防止單一線程長時間獨占CPU)
單核CPU在執(zhí)行的時候,是按照時間片執(zhí)行的,一個時間片只能執(zhí)行一個線程,因為時間片特別的短,我們感受到的就是“同時”進行的。
多核CPU真正意義上做到了一個時間片多個線程同時進行
在單核CPU中,宏觀上同時進行,微觀上順序執(zhí)行
進程是操作系統(tǒng)中資源分配的基本單位,而線程是CPU的基本調(diào)度單位
一個程序運行后至少有一個進程
一個進程可以包含多個線程,但是至少需要有一個線程,否則這個進程是沒有意義的
進程間不能共享數(shù)據(jù)段地址,但通進程的線程之間可以。
1.繼承Thread類
2.重寫run()方法
3.創(chuàng)建子類對象
4.調(diào)用start()方法(PS:不要調(diào)用run()方法,這樣相當于普通調(diào)用對象的方法,并為啟動線程)
繼承類
public class MyThread extends Thread { @Override public void run() { for (int i = 1; i <= 50; i++) { System.out.println("子線程:==>" + i); } }}
測試類
public class TestThread { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); for (int i = 1; i <= 50; i++) { System.out.println("主線程:-->"+i); } }}
結果
getId()
//獲取線程的id,每個線程都有自己的idgetName()
//獲取線程名字Thread.currentThread()
//獲取當前線程
代碼
public class TestThread { public static void main(String[] args) { MyThread t=new MyThread(); t.start(); //只能在繼承Thread類的情況下用 System.out.println("線程id:"+t.getId()); System.out.println("線程名字:"+t.getName()); //調(diào)用Thread類的靜態(tài)方法獲取當前線程(這里獲取的是主線程) System.out.println("線程id:"+Thread.currentThread().getId()); System.out.println("線程名字:"+Thread.currentThread().getName()); }}
只能修改線程的名稱,不能修改線程的id(id是由系統(tǒng)自動分配)
1、使用線程子類的構造方法賦值
2、調(diào)用線程對象的setName()
方法
代碼
public class MyThread extends Thread{ public MyThread() {}//無參構造器 public MyThread(String name) { super(name); } public void run() { for(int i=1;i<=50;i++) {} }}
public class TestThread { public static void main(String[] args) { MyThread t1=new MyThread("子線程1");//通過構造方法 MyThread t2=new MyThread(); t2.setName("子線程2"); System.out.println("線程t1的id:"+t1.getId()+" 名稱:"+t1.getName()); System.out.println("線程t2的id:"+t2.getId()+" 名稱:"+t2.getName()); }}
1.實現(xiàn)
Runnable
接口
2.實現(xiàn)run()
方法
3.創(chuàng)建實現(xiàn)類對象
4.創(chuàng)建線程類對象
5.調(diào)用start()
方法
實現(xiàn)接口
public class MyRunnable implements Runnable{//實現(xiàn)接口 @Override public void run() {//實現(xiàn)run方法 // TODO Auto-generated method stub for(int i=1;i<=10;i++) { System.out.println("子線程:"+i); } }}
測試類
public class TestRunnable { public static void main(String[] args) { //1.創(chuàng)建MyRunnable對象,表示線程執(zhí)行的功能 Runnable runnable=new MyRunnable(); //2.創(chuàng)建線程對象 Thread th=new Thread(runnable); //3.啟動線程 th.start(); for(int i=1;i<=10;i++) { System.out.println("主線程:"+i); } }}
如果一個線程方法我們只使用一次,那么就不必設置一個單獨的類,就可以使用匿名內(nèi)部類實現(xiàn)該功能
public class TestRunnable { public static void main(String[] args) { Runnable runnable=new Runnable() { @Override public void run() { // TODO Auto-generated method stub for(int i=1;i<=10;i++) { System.out.println("子線程:"+ i); } } }; Thread th=new Thread(runnable); th.start(); }}
對比繼承
Thread
類和實現(xiàn)Runnable
接口創(chuàng)建線程的方式發(fā)現(xiàn),都需要有一個run()
方法,但是這個run()方法有不足:
沒有返回值
不能拋出異常
基于上面的兩個不足,在JDK1.5以后出現(xiàn)了第三種創(chuàng)建線程的方式:實現(xiàn)
Callable
接口實現(xiàn)
Callable
接口的好處:
有返回值
能拋出異常
缺點:
創(chuàng)建線程比較麻煩
1.實現(xiàn)
Callable
接口,可以不帶泛型,如果不帶泛型,那么call方法的返回值就是Object
類型2.如果帶泛型,那么call的返回值就是泛型對應的類型
3.從call方法看到:方法有返回值,可以拋出異常
實現(xiàn)接口
import java.util.Random;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;public class TestCallable implements Callable<Integer>{ @Override public Integer call() throws Exception { // TODO Auto-generated method stub return new Random().nextInt(10); }}
測試類
import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;public class Test { public static void main(String[] args) throws InterruptedException, ExecutionException { TestCallable tc=new TestCallable(); FutureTask<Integer> ft=new FutureTask<>(tc); //創(chuàng)建線程對象 Thread th=new Thread(ft); th.start(); //獲取線程得到的返回值 Integer In=ft.get(); System.out.println(In); }}
休眠(當前線程主動休眠millis毫秒)
public static void sleep(long millis)
放棄(當前線程主動放棄時間片,回到就緒狀態(tài),競爭下一次時間片)
public static void yield()
加入(當一個線程調(diào)用了join方法,這個線程就會先被執(zhí)行,它執(zhí)行結束以后才可以去執(zhí)行其余的線程)
public final void join()
//必須先start(),在join(),才有效優(yōu)先級(線程優(yōu)先級為1–10,默認為5,優(yōu)先級越高,表示獲取CPU機會越多)
線程對象.setPriority()
守護線程
線程對象.setDaemon(true);設置為守護線程
線程有兩類:用戶線程(前臺線程)、守護線程(后臺線程)
如果程序中所有前臺線程都執(zhí)行完畢了,后臺線程也會自動結束
垃圾回收器線程屬于守護線程
public static void sleep(long millis)
當前線程主動休眠millis毫秒
子線程
public class SleepThread extends Thread{ @Override public void run() { for (int i = 1; i <= 10; i++) { System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }}
PS:sleep()的異常在run方法中是不能拋出的,只能用try–catch處理
測試類
public class Test01 { public static void main(String[] args) { SleepThread sleepThread = new SleepThread(); sleepThread.start(); }}
結果:每次間隔100ms輸出一次
public static void yield()
當前線程主動放棄時間片,回到就緒狀態(tài),競爭下一次時間片
子線程
public class YieldThread extends Thread{ @Override public void run() { for (int i=1;i<=10;i++){ System.out.println(Thread.currentThread().getName()+":"+i); Thread.yield();//主動放棄資源 } }}
測試類
public class Test01 { public static void main(String[] args) { YieldThread yieldThread01 = new YieldThread(); YieldThread yieldThread02 = new YieldThread(); yieldThread01.start(); yieldThread02.start(); }}
結果:基本都會交替進行,也會有一個線程連輸出
當一個線程調(diào)用了join方法,這個線程就會先被執(zhí)行,它執(zhí)行結束以后才可以去執(zhí)行其余的線程,必須先start,再join才有效
子線程
public class JoinThread extends Thread{ @Override public void run() { for (int i=1;i<=10;i++){ System.out.println(Thread.currentThread().getName()+":"+i); } }}
測試類
public class Test01 { public static void main(String[] args) throws InterruptedException { for (int i=1;i<=10;i++){ System.out.println(Thread.currentThread().getName()+":"+i); if(i==5){ JoinThread joinThread = new JoinThread(); joinThread.start(); joinThread.join(); } } }}
結果:當主線程打印到5的時候,這時候子線程加入進來,就先執(zhí)行完子線程,在執(zhí)行主線程
將子線程設置為主線程的伴隨線程,主線程停止的時候,子線程也不要繼續(xù)執(zhí)行了
注意:先設置,在啟動
子線程
public class TestThread extends Thread{ @Override public void run() { for(int i=1;i<=1000;i++){ System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } }}
測試類
public class Test01 { public static void main(String[] args) throws InterruptedException { TestThread daemonThread = new TestThread(); daemonThread.setDaemon(true);//設置守護線程 daemonThread.start(); for (int i=1;i<=10;i++){ System.out.println(Thread.currentThread().getName()+":"+i); Thread.sleep(100); } }}
結果:當主線程結束時,子線程也跟著結束,并不會繼續(xù)執(zhí)行下去打印輸出
線程優(yōu)先級為1-10,默認為5,優(yōu)先級越高,表示獲取CPU機會越多
子線程
public class TestThread extends Thread{ @Override public void run() { for(int i=1;i<=100;i++){ System.out.println(Thread.currentThread().getName()+":"+i); } }}
測試
public class Test01 { public static void main(String[] args) throws InterruptedException { TestThread th2 = new TestThread(); TestThread th3 = new TestThread(); TestThread th4 = new TestThread(); th2.setPriority(10);//設置線程1優(yōu)先級10 th2.start(); th3.start();//線程2優(yōu)先級默認不變,為5 th4.setPriority(1);//設置線程3優(yōu)先級為1 th4.start(); }}
結果:優(yōu)先級(th2>th3>th4)線程3應該在最后打印
需求:模擬三個窗口,每個窗口有100個人,同時搶10張票
使用繼承Runnable接口的方法
public class BuyTicketRunnable implements Runnable{ private int ticketNum=10; @Override public void run() { for(int i=1;i<=100;i++) { if(ticketNum<=0) break; System.out.println("在"+Thread.currentThread().getName()+"買到了第"+ticketNum+"張票!"); ticketNum--; } }}
測試方法
public class BuyTicketTest { public static void main(String[] args) { // TODO Auto-generated method stub Runnable runnable=new BuyTicketRunnable(); Thread th2=new Thread(runnable,"窗口1"); Thread th3=new Thread(runnable,"窗口2"); Thread th4=new Thread(runnable,"窗口3"); th2.start(); th3.start(); th4.start(); }}
結果
我們發(fā)現(xiàn),不同窗口會搶到同一張票?。?!,這在實際情況是不允許的,這是因為多個線程,在爭搶資源的過程中,導致共享的資源出現(xiàn)問題。一個線程還沒執(zhí)行完,另一個線程就參與進來了,開始爭搶。(但窗口2搶到第10張票,還沒來得及
ticketNum--
操作,時間片就用完了,隨后被窗口三搶到CPU資源,此時的票數(shù)還是10,窗口三也搶到第十張票,也還沒來得及ticketNum--
操作窗口三時間片由完了,窗口一搶到CPU資源,還是買到了第10張票)
多線程安全問題:
當多線程并發(fā)訪問臨界資源時,如果破壞原子操作,可能會造成數(shù)據(jù)不一致
臨界資源:共享資源(同一對象),一次只能允許一個線程使用,才可以保證其正確性
原子操作:不可分割的多步操作,被視作一個整體,其順序和步驟不可被打亂或缺省
synchronized
(同步監(jiān)視器)
必須是引用數(shù)據(jù)類型,不能是基本數(shù)據(jù)類型
也可以創(chuàng)建一個專門的同步監(jiān)視器,沒有任何業(yè)務含義 (new Object)
一般使用共享資源做同步監(jiān)視器即可
在同步代碼塊中不能改變同步監(jiān)視器對象的引用
盡量不要String和包裝類Integer做同步監(jiān)視器,建議使用final修飾同步監(jiān)視器
對賣票案例改進
public class BuyTicketRunnable implements Runnable{ static Object obj=new Object(); private int ticketNum=10; @Override public void run() { for(int i=1;i<100;i++) { //把具有安全隱患的代碼鎖住即可,如果鎖多了就會效率低 synchronized (obj) {//鎖必須多個線程用的是同一把鎖??!也可以使用this,表示的是該對象本身 System.out.println("在"+Thread.currentThread().getName()+"買到了第"+ticketNum+"張票!"); ticketNum--; } } }}
多個代碼塊使用了同一個同步監(jiān)視器(鎖),鎖住一個代碼塊的同時,也鎖住所有使用該鎖的所有代碼塊,其他線程無法訪問其中的任何一個代碼塊
多個代碼塊使用了同一個同步監(jiān)視器(鎖),鎖住一個代碼塊的同時,也鎖住所有使用該鎖的所有代碼塊, 但是沒有鎖住使用其他同步監(jiān)視器的代碼塊,其他線程有機會訪問其他同步監(jiān)視器的代碼塊
synchronized
(同步方法)
不要將run()定義為同步方法
非靜態(tài)同步方法的同步監(jiān)視器是this;靜態(tài)同步方法(static)的同步監(jiān)視器是 類名.class 字節(jié)碼信息對象
同步代碼塊的效率要高于同步方法(原因:同步方法是將線程擋在了方法的外部,而同步代碼塊鎖將線程擋在了代碼塊的外部,但是卻是方法的內(nèi)部)
同步方法的鎖是this,一旦鎖住一個方法,就鎖住了所有的同步方法;同步代碼塊只是鎖住使用該同步監(jiān)視器的代碼塊,而沒有鎖住使用其他監(jiān)視器的代碼塊
買票案例改進
public class BuyTicketRunnable implements Runnable{ private int ticketNum=10; @Override public void run() { for(int i=1;i<100;i++) { BuyTicket(); } } public synchronized void BuyTicket() {//鎖住的是:this,如果是靜態(tài)方法:當前類.class if(ticketNum>0) { System.out.println("在"+Thread.currentThread().getName()+"買到了第"+ticketNum+"張票!"); ticketNum--; } }}
Lock
鎖:
DK1.5后新增新一代的線程同步方式:Lock鎖,與采用synchronized相比,lock可提供多種鎖方案,更靈活
synchronized是Java中的關鍵字,這個關鍵字的識別是靠JVM來識別完成的呀。是虛擬機級別的。
但是Lock鎖是API級別的,提供了相應的接口和對應的實現(xiàn)類,這個方式更靈活,表現(xiàn)出來的性能優(yōu)于之前的方式。
對買票案例改進
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class BuyTicketRunnable implements Runnable{ private int ticketNum=10; Lock lock=new ReentrantLock();//接口=實現(xiàn)類 可以使用不同的實現(xiàn)類 @Override public void run() { for(int i=1;i<100;i++) { lock.lock();//打開鎖 try { if(ticketNum>0) { System.out.println("在"+Thread.currentThread().getName()+"買到了第"+ticketNum+"張票!"); ticketNum--; } }catch(Exception e) { e.printStackTrace(); }finally { //關閉鎖:--->即使有異常,這個鎖也可以得到釋放 lock.unlock(); } } }}
Lock和synchronized的區(qū)別
Lock是顯式鎖(手動開啟和關閉鎖,別忘記關閉鎖),synchronized是隱式鎖
Lock只有代碼塊鎖,synchronized有代碼塊鎖和方法鎖
使用Lock鎖,JVM將花費較少的時間來調(diào)度線程,性能更好。并且具有更好的擴展性(提供更多的子類)
不同的線程分別占用對方需要的同步資源不放棄,都在等待對方放棄自己需要的同步資源,就形成了線程的死鎖
出現(xiàn)死鎖后,不會出現(xiàn)異常,不會出現(xiàn)提示,只是所有的線程都處于阻塞狀態(tài),無法繼續(xù)
*案例:男孩女孩一起去吃飯,但是桌子上只有兩根筷子,如果兩個人同時搶到一根筷子而不放棄,這樣兩個人都吃不上飯,這樣就形成死鎖了;必須要有一個人放棄爭搶,等待另一個人用完,釋放資源,這個人之后才會獲得兩根筷子,兩個人才能都吃上飯 *
package 多線程;class Eat{ //代表兩個筷子 public static Object o1=new Object(); public static Object o2=new Object(); public static void eat() { System.out.println("可以吃飯了"); }}class BoyThread extends Thread{ public void run() { synchronized (Eat.o1) { System.out.println("男孩拿到了第一根筷子!"); synchronized (Eat.o2) { System.out.println("男孩拿到了第二根筷子!"); Eat.eat(); } } }}class GirlThread extends Thread{ public void run() { synchronized (Eat.o2) { System.out.println("女孩拿到了第二根筷子!"); synchronized (Eat.o1) { System.out.println("女孩拿到了第一根筷子!"); Eat.eat(); } } }}public class MyLock { public static void main(String[] args) { BoyThread boy=new BoyThread(); GirlThread girl=new GirlThread(); boy.start(); girl.start(); }}
結果
解決辦法
先讓男孩拿到筷子,線程休眠一下,等待男孩用完筷子,在啟動女孩線程
public class MyLock { public static void main(String[] args) { BoyThread boy=new BoyThread(); GirlThread girl=new GirlThread(); boy.start(); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } girl.start(); }}
在寫程序中要避免這種死鎖:減少同步資源的定義,避免嵌套同步
在Java對象中,有兩種池
鎖池(
synchronized
)等待池(
wait()
;notify()
;notifyAll()
)
如果一個線程調(diào)用了某個對象的wait方法,那么該線程進入到該對象的等待池中(并且已經(jīng)將鎖釋放);
如果未來的某個時刻,另外一個線程調(diào)用了相同的對象notify方法或者notifyAll方法,那么該等待池中的線程就會被喚醒,然后進入到對象的鎖池里面去獲得該對象的鎖;
如果獲得鎖成功后,那么該線程就會沿著wait方法之后的路徑繼續(xù)執(zhí)行。注意:沿著wait方法之后執(zhí)行
wait():的作用是讓當前線程進入等待狀態(tài),同時,wait()也會讓當前線程釋放它所持有的鎖。直到其他線程調(diào)用此對象的
notify()
方法或notifyAll()
方法,當前線程被喚醒(進入就緒狀態(tài))wait(long timeout):讓當前線程處于“等待(阻塞)狀態(tài),直到其他線程調(diào)用此對象的
notify()
方法或notifyAll()
方法,或者超過指定的時間量”,當前線程被喚醒(進入就緒狀態(tài))
sleep和wait的區(qū)別:sleep進入阻塞狀態(tài)沒有釋放鎖,wait進入阻塞狀態(tài)但是同時釋放了鎖
notify()和notifyAll()的作用,則是喚醒當前對象上的等待線程
notify()是喚醒單個線程
notifyAll()是喚醒所有的線程
案例:
假設倉庫中只能存放一件產(chǎn)品,生產(chǎn)者將生產(chǎn)出來的產(chǎn)品放入倉庫,消費者將倉庫中產(chǎn)品取走消費。
如果倉庫中沒有產(chǎn)品,則生產(chǎn)者將產(chǎn)品放入倉庫,否則停止生產(chǎn)并等待,直到倉庫中的產(chǎn)品被消費者取走為止。
如果倉庫中放有產(chǎn)品,則消費者可以將產(chǎn)品取走消費,否則停止消費并等待,直到倉庫中再次放入產(chǎn)品為止。
功能分解一:商品類
public class Product {//商品類 private String name;//名字 private String brand;//品牌 boolean flag = false;//設置標記,false表示商品沒有,等待生產(chǎn)者生產(chǎn) public synchronized void setProduct(String name, String brand) {//生產(chǎn)商品,同步方法,鎖住的是this if (flag == true) {//如果flag為true,代表有商品,不生產(chǎn),等待消費者消費 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //生產(chǎn)商品 this.setName(name); this.setBrand(brand); System.out.println("生產(chǎn)者生產(chǎn)了" +this.getBrand() +this.getName()); //生產(chǎn)完,設置標志 flag = true; //喚醒消費線程 notify(); } public synchronized void getProduct() { if (flag == false) {//如果是false,則沒有商品,等待生產(chǎn)者生產(chǎn) try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果有商品,消費 System.out.println("消費者消費了" + this.getBrand() +this.getName()); //設置標志 flag = false; //喚醒線程 notify(); } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setBrand(String brand) { this.brand = brand; } public String getBrand() { return brand; }}
功能分解二:生產(chǎn)者線程
public class ProducterThread extends Thread {//生產(chǎn)者線程 private Product p; public ProducterThread(Product p) { this.p = p; } @Override public void run() { for (int i = 1; i <= 10; i++) { if(i%2==0){//如果是奇數(shù),就生產(chǎn)巧克力,如果是偶數(shù),就生產(chǎn)方便面 p.setProduct("巧克力","德芙"); }else{ p.setProduct("方便面","康師傅"); } } }}
功能分解三:消費者線程
public class CustomerThread extends Thread {//消費者線程 private Product pro; public CustomerThread(Product pro) { this.pro = pro; } @Override public void run() { for (int i = 1; i <= 10; i++) { pro.getProduct(); } }}
功能分解四:測試類
public class Test { public static void main(String[] args) { Product p = new Product(); ProducterThread pth = new ProducterThread(p); CustomerThread cth = new CustomerThread(p); pth.start(); cth.start(); }}
結果:生產(chǎn)者生產(chǎn)一件商品,消費者消費一件商品,交替進行
到此,相信大家對“java多線程機制是什么”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!
名稱欄目:java多線程機制是什么
本文地址:http://aaarwkj.com/article32/igipsc.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設、網(wǎng)站制作、商城網(wǎng)站、微信小程序、營銷型網(wǎng)站建設、網(wǎng)站維護
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)