青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

cc

  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
  38 隨筆 :: 14 文章 :: 21 評論 :: 0 Trackbacks

線程處理的優(yōu)點是可以創(chuàng)建使用多個執(zhí)行線程的應(yīng)用程序。例如,某一進(jìn)程可以具有管理與用戶交互的用戶界面線程,以及在用戶界面線程等待用戶輸入時執(zhí)行其他任務(wù)的輔助線程。

該教程說明各種線程活動:

  • 創(chuàng)建和執(zhí)行線程
  • 線程同步
  • 線程間交互
  • 使用線程池
  • 使用 mutex 對象保護(hù)共享資源

教程

該教程包含下列示例:

示例 1:創(chuàng)建線程、啟動線程和線程間交互

本示例說明如何創(chuàng)建和啟動線程,并顯示了同時在同一進(jìn)程內(nèi)運行的兩個線程間的交互。請注意,不必停止或釋放線程。這由 .NET Framework 公共語言運行庫自動完成。

程序從創(chuàng)建 Alpha 類型的對象 (oAlpha) 和引用 Alpha 類的 Beta 方法的線程 (oThread) 開始。然后啟動該線程。線程的 IsAlive 屬性允許程序等待,直到線程被初始化(被創(chuàng)建、被分配等)為止。主線程通過 Thread 訪問,而 Sleep 方法通知線程放棄其時間片并在一定毫秒數(shù)期間停止執(zhí)行。然后 oThread 被停止和聯(lián)接。聯(lián)接一個線程將使主線程等待它死亡或等待它在指定的時間后過期。最后,程序嘗試重新啟動 oThread,但由于線程無法在停止(中止)后重新啟動而告失敗。有關(guān)臨時停止執(zhí)行的信息,請參見掛起線程執(zhí)行。

// StopJoin.cs
using System;
using System.Threading;

public class Alpha
{

   // This method that will be called when the thread is started
   public void Beta()
   {
      while (true)
      {
         Console.WriteLine(“Alpha.Beta is running in its own thread.“);
      }
   }
};

public class Simple
{
   public static int Main()
   {
      Console.WriteLine(“Thread Start/Stop/Join Sample“);
      
      Alpha oAlpha = new Alpha();

      // Create the thread object, passing in the Alpha.Beta method
      // via a ThreadStart delegate. This does not start the thread.
      Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));

      // Start the thread
      oThread.Start();

      // Spin for a while waiting for the started thread to become
      // alive:
      while (!oThread.IsAlive);
      
      // Put the Main thread to sleep for 1 millisecond to allow oThread
      // to do some work:
      Thread.Sleep(1);
      
      // Request that oThread be stopped
      oThread.Abort();
      
      // Wait until oThread finishes. Join also has overloads
      // that take a millisecond interval or a TimeSpan object.
      oThread.Join();
      
      Console.WriteLine();
      Console.WriteLine(“Alpha.Beta has finished“);
      
      try 
      {
         Console.WriteLine(“Try to restart the Alpha.Beta thread“);
         oThread.Start();
      }
      catch (ThreadStateException) 
      {
         Console.Write(“ThreadStateException trying to restart Alpha.Beta. “);
         Console.WriteLine(“Expected since aborted threads cannot be restarted.“);
      }
      return 0;
   }
}

輸出示例

Thread Start/Stop/Join Sample
Alpha.Beta is running in its own thread.
Alpha.Beta is running in its own thread.
Alpha.Beta is running in its own thread.
...
...
Alpha.Beta has finished
Try to restart the Alpha.Beta thread
ThreadStateException trying to restart Alpha.Beta. Expected since aborted threads cannot be restarted.

示例 2:同步兩個線程:制造者和使用者

下面的示例顯示如何使用 C# lock 關(guān)鍵字和 Monitor 對象的 Pulse 方法完成同步。Pulse 方法通知等待隊列中的線程對象的狀態(tài)已更改。(有關(guān)脈沖的更多詳細(xì)信息,請參見 Monitor.Pulse 方法)。

本示例創(chuàng)建一個 Cell 對象,它具有兩個方法:ReadFromCellWriteToCell。從 CellProdCellCons 類創(chuàng)建另外兩個對象;這兩個對象均具有調(diào)用 ReadFromCellWriteToCellThreadRun 方法。通過等待依次到達(dá)的來自 Monitor 對象的“脈沖”即可完成同步。也就是說,首先產(chǎn)生一個項(此時使用者等待脈沖),然后發(fā)生一個脈沖,接著使用者使用所產(chǎn)生的項(此時制造者等待脈沖),依此類推。

// MonitorSample.cs
// This example shows use of the following methods of the C# lock keyword
// and the Monitor class 
// in threads:
//      Monitor.Pulse(Object)
//      Monitor.Wait(Object)
using System;
using System.Threading;

public class MonitorSample
{
   public static void Main(String[] args)
   {
      int result = 0;   // Result initialized to say there is no error
      Cell cell = new Cell( );

      CellProd prod = new CellProd(cell, 20);  // Use cell for storage, 
                                               // produce 20 items
      CellCons cons = new CellCons(cell, 20);  // Use cell for storage, 
                                               // consume 20 items

      Thread producer = new Thread(new ThreadStart(prod.ThreadRun));
      Thread consumer = new Thread(new ThreadStart(cons.ThreadRun));
      // Threads producer and consumer have been created, 
      // but not started at this point.

      try
      {
         producer.Start( );
         consumer.Start( );

         producer.Join( );   // Join both threads with no timeout
                             // Run both until done.
         consumer.Join( );  
      // threads producer and consumer have finished at this point.
      }
      catch (ThreadStateException e)
      {
         Console.WriteLine(e);  // Display text of exception
         result = 1;            // Result says there was an error
      }
      catch (ThreadInterruptedException e)
      {
         Console.WriteLine(e);  // This exception means that the thread
                                // was interrupted during a Wait
         result = 1;            // Result says there was an error
      }
      // Even though Main returns void, this provides a return code to 
      // the parent process.
      Environment.ExitCode = result;
   }
}

public class CellProd
{
   Cell cell;         // Field to hold cell object to be used
   int quantity = 1;  // Field for how many items to produce in cell

   public CellProd(Cell box, int request)
   {
      cell = box;          // Pass in what cell object to be used
      quantity = request;  // Pass in how many items to produce in cell
   }
   public void ThreadRun( )
   {
      for(int looper=1; looper<=quantity; looper++)
         cell.WriteToCell(looper);  // “producing“
   }
}

public class CellCons
{
   Cell cell;         // Field to hold cell object to be used
   int quantity = 1;  // Field for how many items to consume from cell

   public CellCons(Cell box, int request)
   {
      cell = box;          // Pass in what cell object to be used
      quantity = request;  // Pass in how many items to consume from cell
   }
   public void ThreadRun( )
   {
      int valReturned;
      for(int looper=1; looper<=quantity; looper++)
      // Consume the result by placing it in valReturned.
         valReturned=cell.ReadFromCell( );
   }
}

public class Cell
{
   int cellContents;         // Cell contents
   bool readerFlag = false;  // State flag
   public int ReadFromCell( )
   {
      lock(this)   // Enter synchronization block
      {
         if (!readerFlag)
         {            // Wait until Cell.WriteToCell is done producing
            try
            {
               // Waits for the Monitor.Pulse in WriteToCell
               Monitor.Wait(this);
            }
            catch (SynchronizationLockException e)
            {
               Console.WriteLine(e);
            }
            catch (ThreadInterruptedException e)
            {
               Console.WriteLine(e);
            }
         }
         Console.WriteLine(“Consume: {0}“,cellContents);
         readerFlag = false;    // Reset the state flag to say consuming
                                // is done.
         Monitor.Pulse(this);   // Pulse tells Cell.WriteToCell that
                                // Cell.ReadFromCell is done.
      }   // Exit synchronization block
      return cellContents;
   }
   
   public void WriteToCell(int n)
   {
      lock(this)  // Enter synchronization block
      {
         if (readerFlag)
         {      // Wait until Cell.ReadFromCell is done consuming.
            try
            {
               Monitor.Wait(this);   // Wait for the Monitor.Pulse in
                                     // ReadFromCell
            }
            catch (SynchronizationLockException e)
            {
               Console.WriteLine(e);
            }
            catch (ThreadInterruptedException e)
            {
               Console.WriteLine(e);
            }
         }
         cellContents = n;
         Console.WriteLine(“Produce: {0}“,cellContents);
         readerFlag = true;    // Reset the state flag to say producing
                               // is done
         Monitor.Pulse(this);  // Pulse tells Cell.ReadFromCell that 
                               // Cell.WriteToCell is done.
      }   // Exit synchronization block
   }
}

輸出示例

Produce: 1
Consume: 1
Produce: 2
Consume: 2
Produce: 3
Consume: 3
...
...
Produce: 20
Consume: 20

示例 3:使用線程池

以下示例顯示如何使用線程池。首先創(chuàng)建 ManualResetEvent 對象,此對象使程序能夠知道線程池何時運行完所有的工作項。接著,嘗試向線程池添加一個線程。如果添加成功,則添加其余的線程(本例中為 4 個)。然后線程池將工作項放入可用線程中。調(diào)用 eventX 上的 WaitOne 方法,這會使程序的其余部分等待,直到用 eventX.Set 方法觸發(fā)事件為止。最后,程序打印出線程上的負(fù)載(實際執(zhí)行某一特定工作項的線程)。

// SimplePool.cs
// Simple thread pool example
using System;
using System.Collections;
using System.Threading;

// Useful way to store info that can be passed as a state on a work item
public class SomeState
{
   public int Cookie;
   public SomeState(int iCookie)
   {
      Cookie = iCookie;
   }
}

public class Alpha
{
   public Hashtable HashCount;
   public ManualResetEvent eventX;
   public static int iCount = 0;
   public static int iMaxCount = 0;
   public Alpha(int MaxCount) 
   {
      HashCount = new Hashtable(MaxCount);
      iMaxCount = MaxCount;
   }

   // Beta is the method that will be called when the work item is
   // serviced on the thread pool.
   // That means this method will be called when the thread pool has
   // an available thread for the work item.
   public void Beta(Object state)
   {
      // Write out the hashcode and cookie for the current thread
      Console.WriteLine(“ {0} {1} :“, Thread.CurrentThread.GetHashCode(),
         ((SomeState)state).Cookie);
      // The lock keyword allows thread-safe modification
      // of variables accessible across multiple threads.
      Console.WriteLine(
         “HashCount.Count=={0}, Thread.CurrentThread.GetHashCode()=={1}“,
         HashCount.Count, 
         Thread.CurrentThread.GetHashCode());
      lock (HashCount) 
      {
         if (!HashCount.ContainsKey(Thread.CurrentThread.GetHashCode()))
            HashCount.Add (Thread.CurrentThread.GetHashCode(), 0);
         HashCount[Thread.CurrentThread.GetHashCode()] = 
            ((int)HashCount[Thread.CurrentThread.GetHashCode()])+1;
      }

      // Do some busy work.
      // Note: Depending on the speed of your machine, if you 
      // increase this number, the dispersement of the thread
      // loads should be wider.
      int iX  = 2000;
      Thread.Sleep(iX);
      // The Interlocked.Increment method allows thread-safe modification
      // of variables accessible across multiple threads.
      Interlocked.Increment(ref iCount);
      if (iCount == iMaxCount)
      {
         Console.WriteLine();
         Console.WriteLine(“Setting eventX “);
         eventX.Set();
      }
   }
}

public class SimplePool
{
   public static int Main(string[] args)
   {
      Console.WriteLine(“Thread Pool Sample:“);
      bool W2K = false;
      int MaxCount = 10;  // Allow a total of 10 threads in the pool
      // Mark the event as unsignaled.
      ManualResetEvent eventX = new ManualResetEvent(false);
      Console.WriteLine(“Queuing {0} items to Thread Pool“, MaxCount);
      Alpha oAlpha = new Alpha(MaxCount);  // Create the work items.
      // Make sure the work items have a reference to the signaling event.
      oAlpha.eventX = eventX;
      Console.WriteLine(“Queue to Thread Pool 0“);
      try
      {
         // Queue the work items, which has the added effect of checking
         // which OS is running.
         ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta),
            new SomeState(0));
         W2K = true;
      }
      catch (NotSupportedException)
      {
         Console.WriteLine(“These API‘s may fail when called on a non-Windows 2000 system.“);
         W2K = false;
      }
      if (W2K)  // If running on an OS which supports the ThreadPool methods.
      {
         for (int iItem=1;iItem < MaxCount;iItem++)
         {
            // Queue the work items:
            Console.WriteLine(“Queue to Thread Pool {0}“, iItem);
            ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta),new SomeState(iItem));
         }
         Console.WriteLine(“Waiting for Thread Pool to drain“);
         // The call to exventX.WaitOne sets the event to wait until
         // eventX.Set() occurs.
         // (See oAlpha.Beta).
         // Wait until event is fired, meaning eventX.Set() was called:
         eventX.WaitOne(Timeout.Infinite,true);
         // The WaitOne won‘t return until the event has been signaled.
         Console.WriteLine(“Thread Pool has been drained (Event fired)“);
         Console.WriteLine();
         Console.WriteLine(“Load across threads“);
         foreach(object o in oAlpha.HashCount.Keys)
            Console.WriteLine(“{0} {1}“, o, oAlpha.HashCount[o]);
      }
      return 0;
   }
}

輸出示例

注意???下列輸出隨計算機的不同而不同。
Thread Pool Sample:
Queuing 10 items to Thread Pool
Queue to Thread Pool 0
Queue to Thread Pool 1
...
...
Queue to Thread Pool 9
Waiting for Thread Pool to drain
 98 0 :
HashCount.Count==0, Thread.CurrentThread.GetHashCode()==98
 100 1 :
HashCount.Count==1, Thread.CurrentThread.GetHashCode()==100
 98 2 :
...
...
Setting eventX
Thread Pool has been drained (Event fired)

Load across threads
101 2
100 3
98 4
102 1

示例 4:使用 Mutex 對象

可以使用 mutex 對象保護(hù)共享資源不被多個線程或進(jìn)程同時訪問。mutex 對象的狀態(tài)或者設(shè)置為終止(當(dāng)它不屬于任何線程時),或者設(shè)置為非終止(當(dāng)它屬于某個線程時)。同時只能有一個線程擁有一個 mutex 對象。例如,為了防止兩個線程同時寫入共享內(nèi)存,每個線程在執(zhí)行訪問該共享內(nèi)存的代碼之前等待 mutex 對象的所屬權(quán)。寫入共享內(nèi)存后,線程將釋放該 mutex 對象。

此示例闡釋如何在處理線程過程中使用 Mutex 類、AutoResetEvent 類和 WaitHandle 類。它還闡釋在處理 mutex 對象過程中所用的方法。

// Mutex.cs
// Mutex object example
using System;
using System.Threading;

public class MutexSample
{
   static Mutex gM1;
   static Mutex gM2;
   const int ITERS = 100;
   static AutoResetEvent Event1 = new AutoResetEvent(false);
   static AutoResetEvent Event2 = new AutoResetEvent(false);
   static AutoResetEvent Event3 = new AutoResetEvent(false);
   static AutoResetEvent Event4 = new AutoResetEvent(false);
   
   public static void Main(String[] args)
   {
      Console.WriteLine(“Mutex Sample ...“);
      // Create Mutex initialOwned, with name of “MyMutex“.
      gM1 = new Mutex(true,“MyMutex“);
      // Create Mutex initialOwned, with no name.
      gM2 = new Mutex(true);
      Console.WriteLine(“ - Main Owns gM1 and gM2“);

      AutoResetEvent[] evs = new AutoResetEvent[4];
      evs[0] = Event1;    // Event for t1
      evs[1] = Event2;    // Event for t2
      evs[2] = Event3;    // Event for t3
      evs[3] = Event4;    // Event for t4

      MutexSample tm = new MutexSample( );
      Thread t1 = new Thread(new ThreadStart(tm.t1Start));
      Thread t2 = new Thread(new ThreadStart(tm.t2Start));
      Thread t3 = new Thread(new ThreadStart(tm.t3Start));
      Thread t4 = new Thread(new ThreadStart(tm.t4Start));
      t1.Start( );   // Does Mutex.WaitAll(Mutex[] of gM1 and gM2)
      t2.Start( );   // Does Mutex.WaitOne(Mutex gM1)
      t3.Start( );   // Does Mutex.WaitAny(Mutex[] of gM1 and gM2)
      t4.Start( );   // Does Mutex.WaitOne(Mutex gM2)

      Thread.Sleep(2000);
      Console.WriteLine(“ - Main releases gM1“);
      gM1.ReleaseMutex( );  // t2 and t3 will end and signal

      Thread.Sleep(1000);
      Console.WriteLine(“ - Main releases gM2“);
      gM2.ReleaseMutex( );  // t1 and t4 will end and signal

      // Waiting until all four threads signal that they are done.
      WaitHandle.WaitAll(evs); 
      Console.WriteLine(“... Mutex Sample“);
   }

   public void t1Start( )
   {
      Console.WriteLine(“t1Start started,  Mutex.WaitAll(Mutex[])“);
      Mutex[] gMs = new Mutex[2];
      gMs[0] = gM1;  // Create and load an array of Mutex for WaitAll call
      gMs[1] = gM2;
      Mutex.WaitAll(gMs);  // Waits until both gM1 and gM2 are released
      Thread.Sleep(2000);
      Console.WriteLine(“t1Start finished, Mutex.WaitAll(Mutex[]) satisfied“);
      Event1.Set( );      // AutoResetEvent.Set() flagging method is done
   }

   public void t2Start( )
   {
      Console.WriteLine(“t2Start started,  gM1.WaitOne( )“);
      gM1.WaitOne( );    // Waits until Mutex gM1 is released
      Console.WriteLine(“t2Start finished, gM1.WaitOne( ) satisfied“);
      Event2.Set( );     // AutoResetEvent.Set() flagging method is done
   }

   public void t3Start( )
   {
      Console.WriteLine(“t3Start started,  Mutex.WaitAny(Mutex[])“);
      Mutex[] gMs = new Mutex[2];
      gMs[0] = gM1;  // Create and load an array of Mutex for WaitAny call
      gMs[1] = gM2;
      Mutex.WaitAny(gMs);  // Waits until either Mutex is released
      Console.WriteLine(“t3Start finished, Mutex.WaitAny(Mutex[])“);
      Event3.Set( );       // AutoResetEvent.Set() flagging method is done
   }

   public void t4Start( )
   {
      Console.WriteLine(“t4Start started,  gM2.WaitOne( )“);
      gM2.WaitOne( );   // Waits until Mutex gM2 is released
      Console.WriteLine(“t4Start finished, gM2.WaitOne( )“);
      Event4.Set( );    // AutoResetEvent.Set() flagging method is done
   }
}

示例輸出

Mutex Sample ...
 - Main Owns gM1 and gM2
t1Start started,  Mutex.WaitAll(Mutex[])
t2Start started,  gM1.WaitOne( )
t3Start started,  Mutex.WaitAny(Mutex[])
t4Start started,  gM2.WaitOne( )
 - Main releases gM1
t2Start finished, gM1.WaitOne( ) satisfied
t3Start finished, Mutex.WaitAny(Mutex[])
 - Main releases gM2
t1Start finished, Mutex.WaitAll(Mutex[]) satisfied
t4Start finished, gM2.WaitOne( )
... Mutex Sample
注意???此示例的輸出可能在每臺計算機上以及每次運行時均各不相同。運行此示例的計算機的速度及其操作系統(tǒng)都能影響輸出的順序。在多線程環(huán)境中,事件可能并不按預(yù)期的順序發(fā)生。
posted on 2006-12-07 15:00 醒目西西 閱讀(207) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久综合九色| 亚洲狼人综合| 亚洲国产高清自拍| 激情综合在线| 狠狠狠色丁香婷婷综合激情| 国产欧美一区二区精品忘忧草| 国产精品理论片| 国产日产亚洲精品| 欧美特黄一级| 免费一级欧美在线大片| 亚洲欧美美女| 欧美在线关看| 美女亚洲精品| 欧美婷婷久久| 国内精品一区二区三区| 亚洲人成人一区二区在线观看| 日韩写真在线| 亚洲自拍偷拍一区| 久久亚洲一区| 亚洲娇小video精品| 亚洲丶国产丶欧美一区二区三区| 亚洲清纯自拍| 性做久久久久久久久| 裸体素人女欧美日韩| 国产精品国产三级国产aⅴ浪潮| 国产亚洲一区二区三区在线观看| 亚洲国产成人精品女人久久久 | 在线一区二区三区四区| 午夜视频久久久久久| 免费一级欧美片在线观看| 亚洲最新视频在线| 老司机一区二区| 国产酒店精品激情| 一区二区三区四区五区精品视频| 久久久蜜桃一区二区人| 日韩视频在线播放| 久久这里有精品视频| 国产精品欧美经典| 夜夜夜久久久| 亚洲第一精品在线| 久久黄色网页| 国产欧美亚洲一区| 中文精品在线| 亚洲激情在线观看视频免费| 久久国产福利| 国产精品一区免费在线观看| 日韩一区二区电影网| 久久综合九色欧美综合狠狠| 亚洲精品在线观看视频| 久久国产精品久久精品国产| 国产精品美女久久久久aⅴ国产馆| 亚洲精品美女久久7777777| 久久亚洲捆绑美女| 久久se精品一区二区| 国产欧美精品va在线观看| 在线视频精品| 日韩网站免费观看| 欧美精品国产| 亚洲精品一二三区| 欧美高清在线播放| 亚洲网站在线观看| 欧美电影专区| 亚洲人久久久| 久久精品视频导航| 亚洲午夜未删减在线观看| 欧美日韩1区2区3区| 亚洲欧洲日韩在线| 亚洲二区免费| 欧美国产三区| 欧美二区在线播放| 日韩视频精品| 99成人免费视频| 欧美无乱码久久久免费午夜一区| 中文av一区二区| 亚洲精品麻豆| 欧美在线视频全部完| 欧美日韩一区二区三区四区五区 | 美国十次了思思久久精品导航| 在线不卡中文字幕播放| 欧美成人影音| 欧美日韩亚洲一区在线观看| 午夜精品久久久久久久男人的天堂 | 久久久久久一区二区| 在线欧美日韩| 亚洲破处大片| 欧美午夜性色大片在线观看| 午夜宅男欧美| 亚洲网站视频| 久久黄色小说| 欧美国产1区2区| 午夜精品视频一区| 久久久999精品| 一本大道av伊人久久综合| 亚洲综合丁香| 亚洲日本欧美| 欧美一区二区三区视频在线观看 | 久久精品视频免费观看| 艳妇臀荡乳欲伦亚洲一区| 欧美一级二级三级蜜桃| 日韩一级大片| 欧美在线高清视频| 亚洲深爱激情| 久久一区中文字幕| 亚洲欧美精品| 国产精品久久久久久模特| 国产美女扒开尿口久久久| 欧美激情一区| 国产一区二区三区在线观看视频 | 欧美制服丝袜第一页| 日韩视频永久免费| 久久不射2019中文字幕| 亚洲视频你懂的| 媚黑女一区二区| 久久精品夜色噜噜亚洲aⅴ| 欧美日韩精品国产| 欧美激情bt| 精品不卡一区| 午夜一级久久| 小黄鸭视频精品导航| 欧美日韩不卡视频| 欧美成人精品一区二区三区| 国产美女精品视频免费观看| 亚洲免费成人| 99精品福利视频| 亚洲国产中文字幕在线观看| 国产一区二区剧情av在线| 亚洲午夜一区二区三区| 中文日韩在线| 欧美日韩视频在线观看一区二区三区| 免费中文字幕日韩欧美| 国产综合激情| 国产一区二区精品久久| 欧美黄色小视频| 亚洲国产精品久久久久| 久久久视频精品| 免费观看久久久4p| 在线观看欧美一区| 久久视频国产精品免费视频在线 | 欧美一级久久久久久久大片| 欧美日韩一区二区三区在线视频 | 亚洲三级视频| 久久国产精品一区二区三区| 久久国产精品久久精品国产 | 欧美成人免费va影院高清| 久久久99精品免费观看不卡| 国产日产欧美a一级在线| 午夜精品国产更新| 久久久久久久久久看片| 狠狠色丁香久久婷婷综合丁香| 欧美一区二区免费视频| 欧美午夜精品电影| 亚洲视频狠狠| 国产欧美一区二区视频| 久久激情网站| 亚洲福利一区| 亚洲午夜电影在线观看| 国产精品青草久久久久福利99| 午夜精品一区二区三区在线视 | 亚洲福利精品| 欧美激情一区二区三区高清视频| 亚洲狼人综合| 欧美色另类天堂2015| 亚洲欧美一区二区三区久久| 久久免费视频观看| 亚洲国产一区二区三区a毛片| 亚洲精品1区| 亚洲影视在线播放| 一区二区三区在线免费观看| 嫩草成人www欧美| 国产精品99久久久久久人| 久久久久综合一区二区三区| 亚洲精品免费看| 亚洲国产成人精品久久| 欧美日韩一级黄| 久久本道综合色狠狠五月| 亚洲激情在线播放| 欧美一区二区三区在线视频| 在线成人激情视频| 国产精品久久| 老司机免费视频久久| 国产精品久久久久久久久久三级 | 亚洲影视九九影院在线观看| 久久精品一区二区三区不卡| 亚洲精品美女| 国产婷婷97碰碰久久人人蜜臀| 欧美freesex8一10精品| 亚洲欧美日产图| 亚洲精品国产日韩| 老司机精品导航| 亚洲欧美精品suv| 亚洲精品在线观看免费| 香蕉国产精品偷在线观看不卡| 亚洲国产精品视频| 久久久91精品国产| 午夜精品福利一区二区三区av | 久久人91精品久久久久久不卡| 亚洲精品中文字幕在线| 亚洲欧美国产高清| 日韩五码在线| 亚洲国产成人精品女人久久久|