精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Eclipse客戶端程序中多線程的使用

開發(fā) 后端
本文分析了Eclipse中多線程程序的實現(xiàn),討論了在Eclipse客戶端程序開發(fā)中應用多線程的方法和要注意的問題,同時也討論了多線程程序的一些調(diào)試和問題解決的方法。

Eclipse 作為一個開發(fā)平臺,使用越來越廣泛,基于Eclipse Rich Client Platform開發(fā)的客戶端程序也越來越多。在當今越來越復雜的應用環(huán)境中,我們的客戶端程序不可避免的要同時進行多任務的處理。一個優(yōu)異的客戶端程序都會允許用戶同時啟動多個任務,從而大大提高用戶的工作效率以及用戶體驗。本文中我們來談談Eclipse中實現(xiàn)多任務的方式。

在我們基于Eclipse的Java程序中,我們有很多種方式提供多任務的實現(xiàn)。熟悉Java的朋友立即會想到Java的Thread類,這是Java中使用最多的一個實現(xiàn)多任務的類。Eclipse平臺為多任務處理提供了自己的API,那就是Job以及UIJob。Eclipse中的Job是對Java Thread的一個封裝,為我們實現(xiàn)多任務提供了更方便的接口。以下是Job的基本用法:


清單 1. Job用法示例
                Job job = new Job(“Job Name”){
protected IStatus run(IProgressMonitor monitor) {

// 在這里添加你的任務代碼
return Status.OK_STATUS;
}
};
job.schedule(delayTime);

在 Eclipse中我們也會經(jīng)常用到Display.asynchExec() 和Display.synchExec()來啟動任務的執(zhí)行。這兩個方法主要為了方便我們完成界面操作的任務。以下是 Display.asynchExec()的用法,Display.synchExec()和它類似。


清單 2. Display.synchExec()用法示例
                Display.getDefault().asyncExec(new Runnable() {
public void run() {
// 在這里添加你的任務代碼
}
});

通常,在Eclipse中我們最好使用Eclipse提供的Job接口來實現(xiàn)多任務,而不是使用Java的thread。為什么呢?主要有以下幾個原因:

  • Job是可重用的工作單元,一個Job我們可以很方便的讓它多次執(zhí)行。
  • Job提供了方便的接口,使得我們在處理中能夠很方便的與外界交流,報告當前的執(zhí)行進度
  • Eclipse提供了相應的機制使得程序員可以方便的介入Job的調(diào)度,例如我們可以方便的實現(xiàn)每次只有一個同一類型的Job在運行
  • Eclipse缺省提供了Job管理的程序,可以查看當前所有的Job和它們的進度,也提供UI終止、暫停、繼續(xù)指定的Job
  • 使用Job可以提高程序的性能,節(jié)省線程創(chuàng)建和銷毀的開銷。Eclipse中的Job封裝了線程池的實現(xiàn)。當我們啟動一個Job時,Eclipse不會馬上新建一個Thread,它會在它的線程池中尋找是否有空閑的線程,如果有空閑線程,就會直接用空閑線程運行你的Job。一個Job終止時,它所對應的線程也不會立即終止,它會被返回到線程池中以備重復利用。這樣,我們可以節(jié)省創(chuàng)建和銷毀線程的開銷

下面我們從幾個方面來討論Eclipse中Job的實現(xiàn)和使用方面的問題。

Eclipse中Job的實現(xiàn)

Eclipse 的核心包中提供了一個JobManager類,它實現(xiàn)了IJobManager接口,Eclipse中Job的管理和調(diào)度都是由JobManager來實現(xiàn)的。 JobManager維護有一個線程池,用來運行Job。當我們調(diào)用Job的schedule方法后,這個Job會被JobManager首先放到一個 Job運行的等待隊列中去。之后,JobManager會通知線程池有新的Job加入了運行等待隊列。線程池會找出一個空閑的線程來運行Job,如果沒有空閑線程,線程池會創(chuàng)建一個新的線程來運行Job。一旦Job運行完畢,運行Job的線程會返回到線程池中以備下次使用。從上面Job運行的過程我們可以看到,JobManager介入了一個Job運行的全過程,它了解Job什么時候開始,什么時候結束,每一時候Job的運行狀態(tài)。JobManager將這些Job運行的信息以接口的方式提供給用戶,同時它也提供了接口讓我們可以介入Job的調(diào)度等,從而我們擁有了更加強大的控制Job的能力。

為了我們更方便的了解Job所處的狀態(tài),JobManager設置Job的一個狀態(tài)標志位,我們可以通過Job的getState方法獲得Job當前的狀態(tài)值以了解其狀態(tài):

  • NONE:當一個Job剛構造的時候,Job就會處于這種狀態(tài)。當一個Job執(zhí)行完畢(包括被取消)后,Job的狀態(tài)也會變回這種狀態(tài)。
  • WAITING:當我們調(diào)用了Job的shedule方法,JobManager會將Job放入等待運行的Job隊列,這時Job的狀態(tài)為WAITING.
  • RUNNING:當一個Job開始執(zhí)行,Job的狀態(tài)會變?yōu)镽UNNING。
  • SLEEPING: 當我們調(diào)用Job的sleep方法后,Job會變成這一狀態(tài)。當我們調(diào)用schudule方法的時候帶上延時的參數(shù),Job的狀態(tài)也會轉(zhuǎn)入這一狀態(tài),在這一段延時等待的時間中,Job都處于這一狀態(tài)。這是一種睡眠狀態(tài),Job在這種狀態(tài)中時不能馬上轉(zhuǎn)入運行。我們可以調(diào)用Job的wakeup方法來將 Job喚醒。這樣,Job又會轉(zhuǎn)入WAITING狀態(tài)等待運行。

Eclipse中的UI線程

另外,在Eclipse的線程處理中,有一個UI線程的概念。Eclipse程序中的主線程是一個特殊的線程,程序啟動后會先執(zhí)行這個線程,也就是我們的 main()函數(shù)所在的線程。作為桌面應用程序,我們的主線程主要負責界面的響應以及繪制界面元素,所以通常我們也叫它UI線程。

以下代碼,編過SWT應用程序的讀者會非常熟悉。它一般出現(xiàn)在main函數(shù)的結尾。下面來仔細分析一下它的詳細情況。

//當窗口未釋放時
while (!shell.isDisposed()) {

//如果display對象事件隊列中沒有了等待的事件,就讓該線程進入等待狀態(tài)
if (!display.readAndDispatch())
display.sleep();

}

上面的程序?qū)嶋H上就是我們UI線程的處理邏輯:當程序啟動后,UI線程會讀取事件等待隊列,看有沒有事件等待處理。如果有,它會進行相應處理,如果沒有它會進入睡眠狀態(tài)。如果有新的事件到來,它又會被喚醒,進行處理。UI線程所需要處理的事件包括用戶的鼠標和鍵盤操作事件,操作系統(tǒng)或程序中發(fā)出的繪制事件。一般來說,處理事件的過程也就是響應用戶操作的過程。

一個好的桌面應用程序需要對用戶的操作作出最快的響應,也就是說我們的UI線程必須盡快的處理各種事件。從我們程序的角度來說,在UI線程中我們不能進行大量的計算或者等待,否則用戶操作事件得不到及時的處理。通常,如果有大量的計算或者需要長時間等待(例如進行網(wǎng)絡操作或者數(shù)據(jù)庫操作)時,我們必須將這些長時間處理的程序單獨開辟出一個線程來執(zhí)行。這樣雖然后臺運行著程序,但也不會影響界面上的操作。

除主線程之外的所有線程都是非UI線程。在Eclipse程序中,我們所有對界面元素的操作都必須放到UI線程中來執(zhí)行,否則會拋出Exception,所以我們要區(qū)分出UI線程和非UI線程,保證我們對UI的操作都在UI線程中執(zhí)行。

如何判斷當前線程是否UI線程: 你可以通過調(diào)用Display.getCurrent()來知道當前線程是否是UI線程。如果Display.getCurrent()返回為空,表示當前不是UI線程。

Eclipse中使用線程的幾種典型情況

  • 控制Job的并發(fā)運行

對于某些Job,為了避免并發(fā)性問題,我們希望同時只有一個這樣的Job在運行,這時我們需要控制Job的并發(fā)運行。在另一種情況下,我們也需要控制Job 的并發(fā)運行:我們在程序中對于一個任務,我們有可能會啟動一個Job來執(zhí)行,對于少量的任務來說,這是可行的,但是如果我們預測可能會同時有大量的任務,如果每一個任務啟動一個Job,我們同時啟動的Job就會非常多。這些Job會侵占大量的資源,影響其他任務的執(zhí)行。我們可以使用Job的rule來實現(xiàn)控制Job的并發(fā)執(zhí)行。簡單的我們可以通過下面的代碼實現(xiàn)。我們先定義一個如下rule:

 private ISchedulingRule Schedule_RULE = new ISchedulingRule() {
public boolean contains(ISchedulingRule rule) {
return this.equals(rule);
}
public boolean isConflicting(ISchedulingRule rule) {
return this.equals(rule);
}
};

對于需要避免同時運行的Job,我們可以將它們的rule設成上面定義的rule。如:

 myjob1.setRule(Schedule_RULE);
myjob2.setRule(Schedule_RULE);

這樣對于myjob1和myjob2這兩個Job,它們不會再同時執(zhí)行。Myjob2會等待myjob1執(zhí)行完再執(zhí)行。這是由Eclipse的JobManager來提供實現(xiàn)的。JobManager可以保證所有啟動的Job中,任意兩個Job的rule是沒有沖突的。我們在上面定義的rule是最簡單的。我們可以重寫isConflicting函數(shù)來實現(xiàn)一些更加復雜的控制,比如控制同時同類型的Job最多只有指定的個數(shù)在運行。但是我們要注意,isConflicting方法不能過于復雜。一旦一個Job的rule與其他Job的rule有沖突,isConflicting方法會調(diào)用很多次。如果其中的計算過于復雜,會影響整體的性能。

  • 根據(jù)需要執(zhí)行Job

由于我們有的Job有可能不是立即執(zhí)行的,在有些情況下,等到該Job準備執(zhí)行的時候,該Job所要執(zhí)行的任務已經(jīng)沒有意義了。這時,我們可以使用Job的 shouldSchedule()和shouldRun()來避免Job的運行。在我們定義一個Job時,我們可以重載shouldSchedule和 shouldRun方法。在這些方法中,我們可以檢查Job運行的一些先決條件,如果這些條件不滿足,我們就可以返回false。JobManager在安排Job運行時,它會先調(diào)用該Job的shouldSchedule方法,如果返回為false,JobManager就不會再安排這個Job運行了。同樣,JobManager在真正啟動一個線程運行一個Job前,它會調(diào)用該Job的shouldRun方法,如果返回false,它不再運行這個 Job。在下面的例子中,我們希望啟動一個Job在十秒鐘之后更新文本框中的內(nèi)容。為了保證我們的Job運行時是有意義的,我們需要確保我們要更新的文本框沒有被銷毀,我們重載了shouldSchedule和shouldRun方法。

Text text = new Text(parent,SWT.NONE);
UIJob refreshJob = new UIJob(“更新界面”){
public IStatus runInUIThread(IProgressMonitor monitor) {

text.setText(“新文本”);
return Status.OK_STATUS;
}
public boolean shouldSchedule(){
return !text.isDisposed();
}
public boolean shouldRun(){
return !text.isDisposed();
}
};
refreshJob.schedule(10000);

  • 在UI線程中涉及長時間處理的任務

我們經(jīng)常碰到這樣一種情況:用戶操作菜單或者按鈕會觸發(fā)查詢大量數(shù)據(jù),數(shù)據(jù)查詢完后更新表格等界面元素。用戶點擊菜單或者按鈕所觸發(fā)的處理程序一般處于UI 線程,為了避免阻塞UI,我們必須把數(shù)據(jù)查詢等費時的工作放到單獨的Job中執(zhí)行,一旦數(shù)據(jù)查詢完畢,我們又必須更新界面,這時我們又需要使用UI線程進行處理。下面是處理這種情況的示例代碼:

 button.addSelectionListener(new SelectionListener(){
public void widgetSelected(SelectionEvent e){
perform();
}

public void widgetDefaultSelected(SelectionEvent e){
perform();
}

private void perform(){
Job job = new Job(“獲取數(shù)據(jù)”){
protected IStatus run(IProgressMonitor monitor){
// 在此添加獲取數(shù)據(jù)的代碼
Display.getDefault().asyncExec(new Runnable(){
public void run(){
// 在此添加更新界面的代碼
}
});
}
};
job.schedule();
}

});

  • 延時執(zhí)行Job,避免無用的Job運行

我們經(jīng)常需要根據(jù)選中的對象刷新我們部分的界面元素。如果我們連續(xù)很快的改變選擇,而每次刷新界面涉及到的區(qū)域比較大時,界面會出現(xiàn)閃爍。從用戶的角度來說,我們很快的改變選擇,希望看到的只是最后選中的結果,中間的界面刷新都是不必要的。

在 Jface中,StructuredViewer提供了addPostSelectionChangedListener方法。如果我們使用這個方法監(jiān)聽 selectionChanged事件,當用戶一直按著方向鍵改變選中時,我們只會收到一個selectionChanged事件。這樣我們可以避免過度的刷新界面。

實際上,Jface中就是通過延時執(zhí)行Job來實現(xiàn)這一功能的。我們也可以自己實現(xiàn)類似功能:

 private final static Object UPDATE_UI_JOBFAMILY = new Object();
tableviewer. addSelectionChangedListener (new ISelectionChangedListener (){

public void selectionChanged(SelectionChangedEvent event){
Job.getJobManager().cancel(UPDATE_UI_JOBFAMILY);
new UIJob("更新界面") {
protected IStatus runInUIThread (IProgressMonitor monitor) {
//更新界面
return Status.OK_STATUS;
}

public boolean belongsTo(Object family){
return family== UPDATE_UI_JOBFAMILY;
}

}.schedule(500);
}
});

首先,我們需要將界面更新的代碼放到一個UIJob中,同時我們將Job延時500毫秒執(zhí)行(我們可以根據(jù)需要改變延時的時間)。如果下一個 selectionChanged事件很快到來,我們的調(diào)用 Job.getJobManager().cancel(UPDATE_UI_JOBFAMILY)將以前未運行的Job取消,這樣只有最后一個Job會真正運行。

  • 在UI線程中等待非UI線程的結束

有時,我們在UI線程中需要等待一個非UI線程執(zhí)行完,我們才能繼續(xù)執(zhí)行。例如,我們在UI線程中要顯示某些數(shù)據(jù),但是這些數(shù)據(jù)又需要從數(shù)據(jù)庫或者遠程網(wǎng)絡獲取。于是,我們會啟動一個非UI的線程去獲取數(shù)據(jù)。而我們的UI線程必須要等待這個非UI線程執(zhí)行完成,我們才能繼續(xù)執(zhí)行。當然,一種簡單的實現(xiàn)方法是使用join。我們可以在UI線程中調(diào)用非UI線程的join方法,這樣我們就可以等待它執(zhí)行完了,我們再繼續(xù)。但是,這會有一個問題。當我們的UI線程等待時,意味著我們的程序不會再響應界面操作,也不會刷新。這樣,用戶會覺得我們的程序象死了一樣沒有反應。這時,我們可以使用ModalContext 類。你可以將你要執(zhí)行的獲取數(shù)據(jù)的任務用ModalContext的run方法來運行(如下)。ModalContext會將你的任務放到一個獨立的非 UI線程中執(zhí)行,并且等待它執(zhí)行完再繼續(xù)執(zhí)行。與join方法不同的是,ModalContext在等待時不會停止UI事件的處理。這樣我們的程序就不會沒有響應了。

try {
ModalContext.run(new IRunnableWithProgress(){
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
/*需要在非UI線程中執(zhí)行的代碼*/
ModalContext.checkCanceled(monitor);
}
}, true, new NullProgressMonitor(), Display.getCurrent());
} catch (InvocationTargetException e) {

} catch (InterruptedException e) {
}

  • 針對相關聯(lián)的Job統(tǒng)一進行處理

有時,我們需要對相關聯(lián)的Job一起處理。例如需要同時取消這些Job,或者等待所有這些Job結束。這時我們可以使用Job Family。對于相關聯(lián)的Job,我們可以將它們設置成同一個Job Family。我們需要重載Job的belongsTo方法以設置一個Job的Job Family。

Private Object MY_JOB_FAMILY = new Object();
Job job = new Job(“Job Name”){
protected IStatus run(IProgressMonitor monitor) {
// 在這里添加你的任務代碼
return Status.OK_STATUS;
}

public boolean belongsTo(Object family){
return MY_JOB_FAMILY.equals(family);
}
};

我們可以使用JobManager的一系列方法針對Job Family進行操作:

Job.getJobManager().cancel(MY_JOB_FAMILY); //取消所有屬于MY_JOB_FAMILY的所有Job
Job.getJobManager().join(MY_JOB_FAMILY); //等待屬于MY_JOB_FAMILY的所有Job結束
Job.getJobManager().sleep(MY_JOB_FAMILY); //將所有屬于MY_JOB_FAMILY的Job轉(zhuǎn)入睡眠狀態(tài)
Job.getJobManager().wakeup(MY_JOB_FAMILY); //將所有屬于MY_JOB_FAMILY的Job喚醒

線程死鎖的調(diào)試和解決技巧

一旦我們使用了線程,我們的程序中就有可能有死鎖的發(fā)生。一旦發(fā)生死鎖,我們發(fā)生死鎖的線程會沒有響應,導致我們程序性能下降。如果我們的UI線程發(fā)生了死鎖,我們的程序會沒有響應,必須要重啟程序。所以在我們多線程程序開發(fā)中,發(fā)現(xiàn)死鎖的情況,解決死鎖問題對提高我們程序的穩(wěn)定性和性能極為重要。

如果我們發(fā)現(xiàn)程序運行異常(例如程序沒有響應),我們首先要確定是否發(fā)生了死鎖。通過下面這些步驟,我們可以確定是否死鎖以及死鎖的線程:

  • 在Eclipse中以Debug模式運行程序
  • 執(zhí)行響應的測試用例重現(xiàn)問題
  • 在Eclipse的Debug View中選中主線程(Thread[main]),選擇菜單Run->Suspend。這時Eclipse會展開主線程的函數(shù)調(diào)用棧,我們就可以看到當前主線程正在執(zhí)行的操作。
  • 通常,Eclipse在等待用戶的操作,它的函數(shù)調(diào)用棧會和以下類似:


    圖片示例
    圖片示例

  • 如果主線程發(fā)生死鎖,函數(shù)調(diào)用棧的最上層一般會是你自己的函數(shù)調(diào)用,你可以查看一下你當前的函數(shù)調(diào)用以確定主線程在等待什么
  • 使用同樣的方法查看其他線程,特別是那些等待UI線程的線程

我們需要找出當前線程相互的等待關系,以便找出死鎖的原因。我們找出死鎖的線程后就可以針對不同情況進行處理:

  • 減小鎖的粒度,增加并發(fā)性
  • 調(diào)整資源請求的次序
  • 將需要等待資源的任務放到獨立的線程中執(zhí)行

Job使用中要注意的問題

  • 不要在Job中使用Thread.sleep方法。如果你想要讓Job進入睡眠狀態(tài),最好用Job的sleep方法。雖然,使用Thread.sleep和 Job的sleep方法達到的效果差不多,但是它們實現(xiàn)的方式完全不同,對系統(tǒng)的影響也不一樣。我們知道Eclipse中Job是由Eclipse的 JobManager來管理的。如果我們調(diào)用Job的sleep方法,JobManager會將Job轉(zhuǎn)入睡眠狀態(tài),與其對應的線程也會重新放入線程池等待運行其他Job。而如果我們在Job中直接調(diào)用Thread.sleep方法,它會直接使運行Job的線程進入睡眠狀態(tài),其他Job就不可能重用這個線程了。同時,雖然運行該Job的線程進入了睡眠狀態(tài),Job的狀態(tài)還是Running(運行狀態(tài)),我們也不能用Job的wakeup方法喚醒該Job了
  • Job 的取消。一般我們會直觀的認為,一旦調(diào)用Job的cancel方法,Job就會停止運行。實際上,這并不一定正確,當Job處于不同的狀態(tài)時,我們調(diào)用 Job的cancel方法所起的效果是不同的。當Job在WAITING狀態(tài)和SLEEPING狀態(tài)時,一旦我們調(diào)用cancel方法,JobManager會將Job直接從等待運行的隊列中刪除,Job不會再運行了,這時cancel方法會返回true。但是如果Job正在運行,cancel方法調(diào)用并不會立即終止Job的運行,它只會設定一個標志,指明這個Job已經(jīng)被取消了。我們可以使用Job的run方法傳入的參數(shù) IProgressMonitor monitor,這個參數(shù)的isCanceled方法會返回Job是否被取消的狀態(tài)。如果需要,我們必須在我們的代碼的適當位置檢查Job是否被取消的標志,作出適當?shù)捻憫A硗猓捎谡{(diào)用Job的cancel方法不一定立即終止Job,如果我們需要等待被取消的Job運行完再執(zhí)行,我們可以用如下代碼:
     if (!job.cancel())
    job.join();

  • Join方法的使用。由于join方法會導致一個線程等待另一個線程,一旦等待線程中擁有一個被等待線程所需要的鎖,就會產(chǎn)生死鎖。當我們的線程中需要用到同步時,這種死鎖的情況非常容易出現(xiàn),所以我們使用join時必須非常小心,盡量以其他方法替代。
  • 避免過時的Job造成的錯誤。由于我們啟動的線程并不一定是馬上執(zhí)行的,當我們的Job開始運行時,情況可能發(fā)生了變化。我們在Job的處理代碼中要考慮到這些情況。一種典型的情況是,我們在啟動一個對話框或者初始化一個ViewPart時,我們會啟動一些 Job去完成一些數(shù)據(jù)讀取的工作,一旦數(shù)據(jù)讀取結束,我們會啟動新的UI Job更新相應的UI。有時,用戶在打開對話框或者View后,馬上關閉了該對話框或者View。這時我們啟動的線程并沒有被中斷,一旦在Job中再去更新UI,就會出錯。在我們的代碼中必須作相應的處理。所以,我們在線程中更新界面元素之前,我們必須先檢查相應的控件是否已經(jīng)被dispose了

結束語

在我們進行基于Eclipse的客戶端開發(fā)時,使用多線程可以大大的提供我們的程序并發(fā)處理能力,同時對于提高用戶體驗也有很好的幫助。但是,多線程程序也有其不利的一面,我們也不要濫用線程:

  • 首先,多線程程序會大大的提高我們程序的復雜度,使得我們的開發(fā)和調(diào)試更加困難
  • 其次,過多的線程容易引發(fā)死鎖、數(shù)據(jù)同步等并發(fā)問題的發(fā)生
  • 另外,由于線程創(chuàng)建和銷毀需要開銷,程序的整體性能可能因為過多線程的使用而下降

所以,我們在使用線程時一定要謹慎。本文對Eclipse線程的討論,希望能對大家使用線程有所幫助。由于實際情況較為復雜,文中所提到的方法僅供參考,讀者對于不同的實際問題需要進行具體分析,從而找出最佳的解決方案。

【編輯推薦】

  1. 開發(fā)Eclipse自定義控件
  2. Eclipse Ganymede:深入RAP
  3. Eclipse中perspective的兩種使用方法詳解
  4. 在Eclipse中使用JUnit4進行單元測試(3)
  5. 奇怪的Eclipse debug異常
責任編輯:book05 來源: 163博客
相關推薦

2011-12-15 11:03:21

JavaNIO

2010-03-17 18:04:55

java Socket

2011-03-25 12:50:29

nagios安裝

2011-08-17 10:10:59

2009-06-10 16:25:02

2011-03-21 14:53:36

Nagios監(jiān)控Linux

2011-04-06 14:24:20

Nagios監(jiān)控Linux

2010-05-26 09:26:43

Cassandra

2012-10-11 17:02:02

IBMdw

2010-05-12 15:46:51

Subversion客

2025-01-10 10:19:40

多線程socket數(shù)據(jù)

2021-09-22 15:46:29

虛擬桌面瘦客戶端胖客戶端

2010-05-31 19:29:46

SVN客戶端配置

2009-08-18 12:51:19

服務器+客戶端

2012-01-13 10:29:37

ibmdw

2010-06-01 13:54:42

TortoiseSVN

2020-04-23 09:32:33

zookeeperCP系統(tǒng)

2011-04-06 14:24:27

Nagios監(jiān)控Linux

2012-03-06 11:28:08

ibmdw

2010-06-01 14:11:11

TortoiseSVN
點贊
收藏

51CTO技術棧公眾號

先锋亚洲精品| 蜜桃国内精品久久久久软件9| 一区二区三区中文字幕精品精品| 2020国产精品久久精品不卡| 日本一区二区不卡在线| 亚洲精品aaaaa| 欧美日韩不卡在线| 国产黄色片免费在线观看| 欧美在线一卡| 国产美女精品一区二区三区| 2019中文字幕在线| 18啪啪污污免费网站| 亚洲欧美日本国产| 日韩欧美黄色动漫| 青春草在线视频免费观看| 日韩一区二区三区不卡| 蜜桃视频在线一区| 97久久国产精品| www.99re6| 亚洲最好看的视频| 欧美成人a∨高清免费观看| 国产主播在线看| av在线麻豆| 国产欧美日韩中文久久| 国产精品久久久久久久天堂第1集 国产精品久久久久久久免费大片 国产精品久久久久久久久婷婷 | 欧美丝袜美女中出在线| 中文字幕中文字幕在线中一区高清| 神马午夜在线观看| 韩国av一区二区三区四区| 欧美孕妇性xx| 久久综合久久鬼| 国产精品99一区二区三区| 日韩精品视频在线免费观看| 欧美高清精品一区二区| 欧美在线va视频| 黄色成人av在线| 黄网站色视频免费观看| 91福利在线视频| 久久久午夜精品理论片中文字幕| 成人在线免费观看一区| 97人妻精品一区二区三区软件| 国产偷自视频区视频一区二区| 欧美插天视频在线播放| 免费91在线观看| 精品久久视频| 亚洲午夜精品久久久久久性色| 黄色免费视频网站| 天堂精品久久久久| 777午夜精品视频在线播放| 中文字幕无码不卡免费视频| 亚洲一区资源| 精品成人av一区| 丰满少妇大力进入| 男男gaygays亚洲| 一区二区三区免费网站| 亚洲色图都市激情| 色老头在线观看| 亚洲精品免费视频| 狠狠噜天天噜日日噜| 最新国产露脸在线观看| 亚洲欧美乱综合| 少妇高潮大叫好爽喷水| 调教一区二区| 夜夜嗨av一区二区三区网页| 免费的一级黄色片| 91美女精品| 欧美日韩在线观看视频| 国产精品少妇在线视频| **在线精品| 欧美性做爰猛烈叫床潮| 久久99爱视频| 国产精品色婷婷在线观看| 日韩视频免费观看高清完整版| 特级黄色片视频| 98视频精品全部国产| 亚洲第一视频网站| 亚洲专区区免费| 成人中文视频| 久久手机免费视频| 久久精品国产亚洲av香蕉| 最新日韩欧美| 国产精品久久久久久久久久尿 | 蜜臀av一级做a爰片久久| 国产精品亚洲精品| 99国产精品一区二区三区| 国产91富婆露脸刺激对白| 精品国产一二| 成人激情电影在线看| 亚洲情趣在线观看| 国产妇女馒头高清泬20p多| 在线能看的av网址| 欧美日韩在线播放一区| 亚洲AV成人精品| 亚洲成aⅴ人片久久青草影院| 中文字幕亚洲欧美在线| 激情小说中文字幕| 丝袜美腿一区二区三区| 91亚洲va在线va天堂va国| 国产小视频一区| 日本一二三不卡| 91动漫在线看| 成人18视频在线观看| 日韩三级中文字幕| 日本xxxxxxxxx18| 永久亚洲成a人片777777| 欧美一级大胆视频| 国产偷人妻精品一区二区在线| 99久久99久久精品国产片果冻| 亚洲v国产v| 亚洲电影视频在线| 欧美性受xxxx| 亚洲国产综合视频| 五月激情久久久| 国产成人在线一区二区| 精品人妻少妇AV无码专区 | 日韩欧美亚洲国产精品字幕久久久 | 国产成人免费在线观看不卡| 日韩福利在线| free性m.freesex欧美| 欧美精品丝袜久久久中文字幕| 99re久久精品国产| 欧美在线国产| 91精品久久久久久久久久久久久| 五月天丁香视频| 一区二区三区欧美久久| 欧美午夜aaaaaa免费视频| 黄色美女久久久| 久久av红桃一区二区小说| 波多野结衣小视频| 91亚洲男人天堂| 日产精品久久久久久久蜜臀| 欧美另类激情| 这里只有精品丝袜| 99超碰在线观看| 99re这里只有精品6| 国产精品国三级国产av| 99久久这里有精品| 中文字幕不卡av| 亚洲 日本 欧美 中文幕| 97久久精品人人澡人人爽| 99中文字幕在线观看| 精品视频在线观看网站| 最近更新的2019中文字幕| 五月天婷婷导航| 久久综合精品国产一区二区三区| 欧美午夜小视频| 久久91在线| 久久久亚洲成人| 国产刺激高潮av| 午夜精品福利一区二区蜜股av| 伊人av在线播放| 欧美涩涩视频| 国产一区二区免费在线观看| 日本电影在线观看| 欧美成人vr18sexvr| 久久久久亚洲av片无码下载蜜桃 | 亚洲欧美日韩偷拍| 国内精品久久久久久久97牛牛| 亚洲xxx自由成熟| av在线麻豆| 亚洲丁香久久久| 国产 日韩 欧美 在线| 久久综合狠狠综合| 超碰影院在线观看| 欧美理论在线播放| 国产一区二区在线播放| 成人在线免费看黄| 日韩区在线观看| 久久9999久久免费精品国产| 成人动漫一区二区在线| 18岁网站在线观看| 精品欧美久久| 亚洲字幕在线观看| av3级在线| 亚洲人成在线观| 国产精品久久久久久久久久久久久久久久 | 青草综合视频| 色综合久久悠悠| 天天射天天操天天干| 91福利国产精品| 尤物在线免费视频| av电影在线观看完整版一区二区| 免费在线激情视频| 久久精品国产68国产精品亚洲| 91亚洲永久免费精品| 丁香花在线高清完整版视频| 亚洲男人7777| 国产精品九九九九| 亚洲成人av电影在线| 人妻av无码一区二区三区| 美腿丝袜在线亚洲一区| 日韩在线视频在线| 九九视频精品全部免费播放| 91在线视频一区| 中文字幕21页在线看| 久久久成人精品视频| 日韩一级片免费在线观看| 欧美色视频在线观看| 久久久精品人妻一区二区三区四| 久久综合狠狠综合久久综合88 | 91麻豆精品在线| 一区二区高清在线| 欧美成人国产精品一区二区| 国产精品影视天天线| 亚洲一二三区av| 好吊视频一区二区三区四区| 五月天久久狠狠| 国产伦精品一区二区三区免费优势 | 国产麻豆91精品| 狠狠操精品视频| 激情久久久久久久| 正在播放一区二区三区| 三级精品视频| 国产日韩欧美一区二区三区四区| 国产成人77亚洲精品www| 97视频在线免费观看| h片在线免费| 中文字幕v亚洲ⅴv天堂| 青青草视频在线观看| 日韩欧美电影一区| 伊人成人在线观看| 欧美日韩一区二区三区| 久久久久久久久久久久久久免费看 | 91在线播放网址| 波多野结衣三级视频| 久久99国产精品尤物| 成年人网站大全| 国产精品一国产精品k频道56| 欧美交换配乱吟粗大25p| 国产精品毛片一区二区在线看| 欧洲精品亚洲精品| 天天躁日日躁成人字幕aⅴ| 99re视频| 日韩一二三区| 亚洲一区二区三区久久| 欧美在线一级| 国产精品久久久久久久天堂 | 91亚洲精品一区二区| 亚洲爽爆av| 国产一区二区在线免费| 综合久草视频| 亚洲bt天天射| 韩国三级大全久久网站| 91欧美精品成人综合在线观看| 欧美亚洲黄色| 91九色在线视频| 国产精品xnxxcom| 亚洲精品免费在线视频| 日韩高清在线观看一区二区| 亚洲最大av网站| 秋霞影院一区| 国产精品一国产精品最新章节| 亚洲精品高潮| 国产久一道中文一区| 国产亚洲成av人片在线观黄桃| 国产66精品久久久久999小说| 永久免费精品视频| 国产精品日韩欧美一区二区| 国产一区二区三区不卡av| 国产欧美韩日| 日韩精品社区| 日韩免费av电影| 91日韩免费| 69精品丰满人妻无码视频a片| 欧美另类综合| 国产中文字幕视频在线观看| 亚洲影视综合| 一路向西2在线观看| 国产在线一区二区| 精品国产一二区| 99re这里只有精品视频首页| 精品成人无码一区二区三区| 国产精品久久久久久久蜜臀| 精品无码一区二区三区蜜臀| 亚洲精品国产第一综合99久久| 国产一级二级毛片| 岛国av一区二区| 91porny九色| 91精选在线观看| 神宫寺奈绪一区二区三区| 亚洲欧洲国产一区| 麻豆av在线导航| 欧美黑人一级爽快片淫片高清| 黄色软件视频在线观看| 国产精品欧美一区二区| 欧美精品影院| 欧美日本韩国一区二区三区| 日韩一区二区在线免费| 日本男女交配视频| 亚洲一区区二区| www.cao超碰| 99这里只有久久精品视频| 美国黄色特级片| 亚洲午夜精品在线| 超碰在线观看91| 精品剧情在线观看| 国产三区四区在线观看| 欧美成人精品xxx| 免费观看欧美大片| 91麻豆国产语对白在线观看| 欧美色图五月天| 天天做天天爱天天高潮| 性娇小13――14欧美| 91国内在线播放| 91麻豆免费在线观看| www深夜成人a√在线| 婷婷国产在线综合| 国产一区二区三区黄片| 日韩精品中文字| 五月天激情在线| 国产精品第二页| 国偷自产av一区二区三区| 欧美亚洲视频一区| 久久精品主播| 香蕉久久久久久av成人| 国产精品视频线看| 国产欧美一区二区三区在线看蜜臂| 在线电影院国产精品| 男女污污视频在线观看| 欧美精品福利视频| 91精品福利观看| 天堂一区二区三区| 欧美亚洲自偷自偷| 国产精品一区二区在线免费观看| 自拍av一区二区三区| 在线观看国产成人| 亚洲天堂精品在线| 小视频免费在线观看| 国产精品国产三级欧美二区| 亚洲精品一二三区区别| 亚洲天堂网一区| 国产亚洲欧美在线| 人妻 日韩精品 中文字幕| 亚洲国产成人精品女人久久久 | 91caoporn在线| 国产精品免费久久久久久| 自拍偷拍欧美一区| av动漫在线看| 91尤物视频在线观看| 日本一级淫片色费放| 亚洲精品一区二区三区在线观看| 91亚洲天堂| 亚洲自拍偷拍色图| 欧美成人午夜| 亚洲午夜精品在线观看| 亚洲欧美日韩中文字幕一区二区三区 | 亚洲高清网站| 免费不卡的av| 亚洲成a人片在线不卡一二三区| 丰满人妻一区二区三区免费视频| 欧美成人免费小视频| 精品亚洲二区| 精品视频在线观看一区二区| 国产成人精品免费一区二区| 欧美精品入口蜜桃| 精品88久久久久88久久久| 超碰在线网站| 国产综合色一区二区三区| 一本不卡影院| 日韩在线免费观看av| 色噜噜狠狠色综合欧洲selulu| 黄色片视频在线观看| 国产精品久久久久久久久久新婚 | 欧美一级欧美一级| 成人av一区二区三区| 久久99精品波多结衣一区| 国产亚洲成av人片在线观看桃| 国产精成人品2018| 在线无限看免费粉色视频| 国产精品1区2区3区在线观看| 久久综合色综合| 亚洲欧美三级在线| 国精品产品一区| 一级特黄妇女高潮| www.色精品| 国产suv精品一区二区33| 中文字幕成人精品久久不卡| 激情综合五月| 欧美日韩在线不卡视频| 国产精品人成在线观看免费| 99热这里是精品| 97成人精品区在线播放| 精品国精品国产自在久国产应用| 亚洲久久中文字幕| 一区二区三区精品视频| 男人av在线| 97视频中文字幕| 日韩精品一二三四| 欧美高清视频一区二区三区| 亚洲免费福利视频| 国产精品一区二区精品视频观看 | 爱草tv视频在线观看992| 性刺激综合网| 99视频精品在线| 国产精品欧美激情在线| 91av视频在线观看| 91精品国产91久久久久久黑人| 激情综合丁香五月| 5月丁香婷婷综合| 久久电影tv|