C# 多線程及同步簡介示例

60年代,在OS中能擁有資源和獨立運行的基本單位是進程,然而隨著計算機技術的發展,進程出現了很多弊端,一是由于進程是資源擁有者,創建、撤消與切換存在較大的時空開銷,因此需要引入輕型進程;二是由于對稱多處理機(SMP)出現,可以滿足多個運行單位,而多個進程并行開銷過大。
因此在80年代,出現了能獨立運行的基本單位——線程(Threads)。
線程,有時被稱為輕量級進程(Lightweight Process,LWP),是程序執行流的最小單元。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。一個線程可以創建和撤消另一個線程,同一進程中的多個線程之間可以并發執行。由于線程之間的相互制約,致使線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。就緒狀態是指線程具備運行的所有條件,邏輯上可以運行,在等待處理機;運行狀態是指線程占有處理機正在運行;阻塞狀態是指線程在等待一個事件(如某個信號量),邏輯上不可執行。每一個程序都至少有一個線程,若程序只有一個線程,那就是程序本身。
線程是程序中一個單一的順序控制流程。進程內一個相對獨立的、可調度的執行單元,是系統獨立調度和分派CPU的基本單位指運行中的程序的調度單位。在單個程序中同時運行多個線程完成不同的工作,稱為多線程。

?

一、線程簡義

1、進程與線程:進程作為操作系統執行程序的基本單位,擁有應用程序的資源,進程包含線程,進程的資源被線程共享,線程不擁有資源。

2、前臺線程和后臺線程:通過Thread類新建線程默認為前臺線程。當所有前臺線程關閉時,所有的后臺線程也會被直接終止,不會拋出異常。

3、掛起(Suspend)和喚醒(Resume):由于線程的執行順序和程序的執行情況不可預知,所以使用掛起和喚醒容易發生死鎖的情況,在實際應用中應該盡量少用。

4、阻塞線程:Join,阻塞調用線程,直到該線程終止。

5、終止線程:Abort:拋出 ThreadAbortException 異常讓線程終止,終止后的線程不可喚醒。Interrupt:拋出 ThreadInterruptException 異常讓線程終止,通過捕獲異常可以繼續執行。

6、線程優先級:AboveNormal BelowNormal Highest Lowest Normal,默認為Normal。

二、線程的使用

線程函數通過委托傳遞,可以不帶參數,也可以帶參數(只能有一個參數),可以用一個類或結構體封裝參數。

 1 namespace Test
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             Thread t1 = new Thread(new ThreadStart(TestMethod));
 8             Thread t2 = new Thread(new ParameterizedThreadStart(TestMethod));
 9             t1.IsBackground = true;
10             t2.IsBackground = true;
11             t1.Start();
12             t2.Start("hello");
13             Console.ReadKey();
14         }
15 
16         public static void TestMethod()
17         {
18             Console.WriteLine("不帶參數的線程函數");
19         }
20 
21         public static void TestMethod(object data)
22         {
23             string datastr = data as string;
24             Console.WriteLine("帶參數的線程函數,參數為:{0}", datastr);
25         }
26     } 
27 }

?

三、線程池

由于線程的創建和銷毀需要耗費一定的開銷,過多的使用線程會造成內存資源的浪費,出于對性能的考慮,于是引入了線程池的概念。線程池維護一個請求隊列,線程池的代碼從隊列提取任務,然后委派給線程池的一個線程執行,線程執行完不會被立即銷毀,這樣既可以在后臺執行任務,又可以減少線程創建和銷毀所帶來的開銷。

線程池線程默認為后臺線程(IsBackground)。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //將工作項加入到線程池隊列中,這里可以傳遞一個線程參數
 6             ThreadPool.QueueUserWorkItem(TestMethod, "Hello");
 7             Console.ReadKey();
 8         }
 9 
10         public static void TestMethod(object data)
11         {
12             string datastr = data as string;
13             Console.WriteLine(datastr);
14         }
15     }

?

四、Task類

使用ThreadPool的QueueUserWorkItem()方法發起一次異步的線程執行很簡單,但是該方法最大的問題是沒有一個內建的機制讓你知道操作什么時候完成,有沒有一個內建的機制在操作完成后獲得一個返回值。為此,可以使用System.Threading.Tasks中的Task類。

構造一個Task<TResult>對象,并為泛型TResult參數傳遞一個操作的返回類型。

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000);
 6             t.Start();
 7             t.Wait();
 8             Console.WriteLine(t.Result);
 9             Console.ReadKey();
10         }
11 
12         private static Int32 Sum(Int32 n)
13         {
14             Int32 sum = 0;
15             for (; n > 0; --n)
16                 checked{ sum += n;} //結果太大,拋出異常
17             return sum;
18         }
19     }

?

一個任務完成時,自動啟動一個新任務。
一個任務完成后,它可以啟動另一個任務,下面重寫了前面的代碼,不阻塞任何線程。

 1  class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000);
 6             t.Start();
 7             //t.Wait();
 8             Task cwt = t.ContinueWith(task => Console.WriteLine("The result is {0}",t.Result));
 9             Console.ReadKey();
10         }
11 
12         private static Int32 Sum(Int32 n)
13         {
14             Int32 sum = 0;
15             for (; n > 0; --n)
16                 checked{ sum += n;} //結果溢出,拋出異常
17             return sum;
18         }
19     }

?

五、委托異步執行

委托的異步調用:BeginInvoke() 和 EndInvoke()

 1  public delegate string MyDelegate(object data);
 2     class Program
 3     {
 4         static void Main(string[] args)
 5         {
 6             MyDelegate mydelegate = new MyDelegate(TestMethod);
 7             IAsyncResult result = mydelegate.BeginInvoke("Thread Param", TestCallback, "Callback Param");
 8 
 9             //異步執行完成
10             string resultstr = mydelegate.EndInvoke(result);
11         }
12 
13         //線程函數
14         public static string TestMethod(object data)
15         {
16             string datastr = data as string;
17             return datastr;
18         }
19 
20         //異步回調函數
21         public static void TestCallback(IAsyncResult data)
22         {
23             Console.WriteLine(data.AsyncState);
24         }
25     }

?

六、線程同步

  1)原子操作(Interlocked):幫助保護免受計劃程序切換上下文時某個線程正在更新可以由其他線程訪問的變量或者在單獨的處理器上同時執行兩個線程就可能出現的錯誤。 此類的成員不會引發異常。

 1 class Program
 2     {
 3         static int counter = 1;
 4 
 5         static void Main(string[] args)
 6         {
 7             Thread t1 = new Thread(new ThreadStart(F1));
 8             Thread t2 = new Thread(new ThreadStart(F2));
 9 
10             t1.Start();
11             t2.Start();
12 
13             t1.Join();
14             t2.Join();
15 
16             System.Console.ReadKey();
17         }
18 
19         static void F1()
20         {
21             for (int i = 0; i < 5; i++)
22             {
23                 Interlocked.Increment(ref counter);
24                 System.Console.WriteLine("Counter++ {0}", counter);
25                 Thread.Sleep(10);
26             }
27         }
28 
29         static void F2()
30         {
31             for (int i = 0; i < 5; i++)
32             {
33                 Interlocked.Decrement(ref counter);
34                 System.Console.WriteLine("Counter-- {0}", counter);
35                 Thread.Sleep(10);
36             }
37         }
38     }

?

  2)lock()語句:避免鎖定public類型,否則實例將超出代碼控制的范圍,定義private對象來鎖定。而自定義類推薦用私有的只讀靜態對象,比如:private static readonly object obj = new object();為什么要設置成只讀的呢?這時因為如果在lock代碼段中改變obj的值,其它線程就暢通無阻了,因為互斥鎖的對象變了,object.ReferenceEquals必然返回false。Array 類型提供 SyncRoot。許多集合類型也提供 SyncRoot。

  3)Monitor實現線程同步

    通過Monitor.Enter() 和 Monitor.Exit()實現排它鎖的獲取和釋放,獲取之后獨占資源,不允許其他線程訪問。

    還有一個TryEnter方法,請求不到資源時不會阻塞等待,可以設置超時時間,獲取不到直接返回false。

 1         public void MonitorSomeThing()
 2         {
 3             try
 4             {
 5                 Monitor.Enter(obj);
 6                 dosomething();
 7             }
 8             catch(Exception ex)
 9             {
10                 
11             }
12             finally
13             {
14                 Monitor.Exit(obj);
15             }
16         }

?

  4)ReaderWriterLock

    當對資源操作讀多寫少的時候,為了提高資源的利用率,讓讀操作鎖為共享鎖,多個線程可以并發讀取資源,而寫操作為獨占鎖,只允許一個線程操作。

  1 class SynchronizedCache  
  2     {  
  3         private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();  
  4         private Dictionary<int, string> innerCache = new Dictionary<int, string>();  
  5   
  6         public string Read(int key)  
  7         {  
  8             cacheLock.EnterReadLock();  
  9             try  
 10             {  
 11                 return innerCache[key];  
 12             }  
 13             finally  
 14             {  
 15                 cacheLock.ExitReaderLock();  
 16             }  
 17         }  
 18   
 19         public void Add(int key, string value)  
 20         {  
 21             cacheLock.EnterWriteLock();  
 22             try  
 23             {  
 24                 innerCache.Add(key, value);  
 25             }  
 26             finally  
 27             {  
 28                 cacheLock.ExitWriteLock();  
 29             }  
 30         }  
 31   
 32         public bool AddWithTimeout(int key, string value, int timeout)  
 33         {  
 34             if (cacheLock.TryEnterWriteLock(timeout))  
 35             {  
 36                 try  
 37                 {  
 38                     innerCache.Add(key, value);  
 39                 }  
 40                 finally  
 41                 {  
 42                     cacheLock.ExitReaderLock();  
 43                 }  
 44                 return true;  
 45             }  
 46             else  
 47             {  
 48                 return false;  
 49             }  
 50         }  
 51   
 52         public AddOrUpdateStatus AddOrUpdate(int key, string value)  
 53         {  
 54             cacheLock.EnterUpgradeableReadLock();  
 55             try  
 56             {  
 57                 string result = null;  
 58                 if (innerCache.TryGetValue(key, out result))  
 59                 {  
 60                     if (result == value)  
 61                     {  
 62                         return AddOrUpdateStatus.Unchanged;  
 63                     }  
 64                     else  
 65                     {  
 66                         cacheLock.EnterWriteLock();  
 67                         try  
 68                         {  
 69                             innerCache[key] = value;  
 70                         }  
 71                         finally  
 72                         {  
 73                             cacheLock.ExitWriteLock();  
 74                         }  
 75                         return AddOrUpdateStatus.Updated;  
 76                     }  
 77                 }  
 78                 else  
 79                 {  
 80                     cacheLock.EnterWriteLock();  
 81                     try  
 82                     {  
 83                         innerCache.Add(key, value);  
 84                     }  
 85                     finally  
 86                     {  
 87                         cacheLock.ExitWriteLock();  
 88                     }  
 89                     return AddOrUpdateStatus.Added;  
 90                 }  
 91             }  
 92             finally  
 93             {  
 94                 cacheLock.ExitUpgradeableReadLock();  
 95             }  
 96         }  
 97   
 98         public void Delete(int key)  
 99         {  
100             cacheLock.EnterWriteLock();  
101             try  
102             {  
103                 innerCache.Remove(key);  
104             }  
105             finally  
106             {  
107                 cacheLock.ExitWriteLock();  
108             }  
109         }  
110   
111         public enum AddOrUpdateStatus  
112         {  
113             Added,  
114             Updated,  
115             Unchanged  
116         };  
117     }

?

  5)事件(Event)類實現同步

    事件類有兩種狀態,終止狀態和非終止狀態,終止狀態時調用WaitOne可以請求成功,通過Set將時間狀態設置為終止狀態。

    1)AutoResetEvent(自動重置事件)

    2)ManualResetEvent(手動重置事件)

? ? ? ? ? ? ??AutoResetEvent和ManualResetEvent這兩個類經常用到, 他們的用法很類似,但也有區別。Set方法將信號置為發送狀態,Reset方法將信號置為不發送狀態,WaitOne等待信號的發送。可以通過構造函數的參數值來決定其初始狀態,若為true則非阻塞狀態,為false為阻塞狀態。如果某個線程調用WaitOne方法,則當信號處于發送狀態時,該線程會得到信號, 繼續向下執行。其區別就在調用后,AutoResetEvent.WaitOne()每次只允許一個線程進入,當某個線程得到信號后,AutoResetEvent會自動又將信號置為不發送狀態,則其他調用WaitOne的線程只有繼續等待.也就是說,AutoResetEvent一次只喚醒一個線程;而ManualResetEvent則可以喚醒多個線程,因為當某個線程調用了ManualResetEvent.Set()方法后,其他調用WaitOne的線程獲得信號得以繼續執行,而ManualResetEvent不會自動將信號置為不發送。也就是說,除非手工調用了ManualResetEvent.Reset()方法,則ManualResetEvent將一直保持有信號狀態,ManualResetEvent也就可以同時喚醒多個線程繼續執行。

  6)信號量(Semaphore)

      信號量是由內核對象維護的int變量,為0時,線程阻塞,大于0時解除阻塞,當一個信號量上的等待線程解除阻塞后,信號量計數+1。

      線程通過WaitOne將信號量減1,通過Release將信號量加1,使用很簡單。

 1         public Thread thrd;
 2         //創建一個可授權2個許可證的信號量,且初始值為2
 3         static Semaphore sem = new Semaphore(2, 2);
 4  
 5         public mythread(string name)
 6         {
 7             thrd = new Thread(this.run);
 8             thrd.Name = name;
 9             thrd.Start();
10         }
11         void run()
12         {
13             Console.WriteLine(thrd.Name + "正在等待一個許可證……");
14             //申請一個許可證
15             sem.WaitOne();
16             Console.WriteLine(thrd.Name + "申請到許可證……");
17             for (int i = 0; i < 4 ; i++)
18             {
19                 Console.WriteLine(thrd.Name + "" + i);
20                 Thread.Sleep(1000);
21             }
22             Console.WriteLine(thrd.Name + " 釋放許可證……");
23             //釋放
24             sem.Release();
25         }
26     }
27  
28     class mysemaphore
29     {
30         public static void Main()
31         {
32             mythread mythrd1 = new mythread("Thrd #1");
33             mythread mythrd2 = new mythread("Thrd #2");
34             mythread mythrd3 = new mythread("Thrd #3");
35             mythread mythrd4 = new mythread("Thrd #4");
36             mythrd1.thrd.Join();
37             mythrd2.thrd.Join();
38             mythrd3.thrd.Join();
39             mythrd4.thrd.Join();
40         }
41     } 

?

  7)互斥體(Mutex)

      獨占資源,可以把Mutex看作一個出租車,乘客看作線程。乘客首先等車,然后上車,最后下車。當一個乘客在車上時,其他乘客就只有等他下車以后才可以上車。而線程與C# Mutex對象的關系也正是如此,線程使用Mutex.WaitOne()方法等待C# Mutex對象被釋放,如果它等待的C# Mutex對象被釋放了,它就自動擁有這個對象,直到它調用Mutex.ReleaseMutex()方法釋放這個對象,而在此期間,其他想要獲取這個C# Mutex對象的線程都只有等待。

 1 class Test
 2     {
 3         /// <summary>
 4         /// 應用程序的主入口點。
 5         /// </summary>
 6         [STAThread]
 7         static void Main(string[] args)
 8         {
 9             bool flag = false;
10             System.Threading.Mutex mutex = new System.Threading.Mutex(true, "Test", out flag);
11             //第一個參數:true--給調用線程賦予互斥體的初始所屬權
12             //第一個參數:互斥體的名稱
13             //第三個參數:返回值,如果調用線程已被授予互斥體的初始所屬權,則返回true
14             if (flag)
15             {
16                 Console.Write("Running");
17             }
18             else
19             {
20                 Console.Write("Another is Running");
21                 System.Threading.Thread.Sleep(5000);//線程掛起5秒鐘
22                 Environment.Exit(1);//退出程序
23             }
24             Console.ReadLine();
25         }
26     }

?

?  8)跨進程間的同步

      通過設置同步對象的名稱就可以實現系統級的同步,不同應用程序通過同步對象的名稱識別不同同步對象。

 1  static void Main(string[] args)
 2         {
 3             string MutexName = "InterProcessSyncName";
 4             Mutex SyncNamed;     //聲明一個已命名的互斥對象
 5              try
 6             {
 7                 SyncNamed = Mutex.OpenExisting(MutexName);       //如果此命名互斥對象已存在則請求打開
 8             }
 9             catch (WaitHandleCannotBeOpenedException)
10             {
11                 SyncNamed = new Mutex(false, MutexName);         //如果初次運行沒有已命名的互斥對象則創建一個
12             }
13             Task MulTesk = new Task
14                 (
15                     () =>                  //多任務并行計算中的匿名方法,用委托也可以
16                     {
17                         for (; ; )         //為了效果明顯而設計
18                         {
19                             Console.WriteLine("當前進程等待獲取互斥訪問權......");
20                             SyncNamed.WaitOne();
21                             Console.WriteLine("獲取互斥訪問權,訪問資源完畢,按回車釋放互斥資料訪問權.");
22                             Console.ReadLine();
23                             SyncNamed.ReleaseMutex();
24                             Console.WriteLine("已釋放互斥訪問權。");
25                         }
26                     }
27                 );
28             MulTesk.Start();
29             MulTesk.Wait();
30         }

?  9)分布式的同步

  可以使用redis任務隊列或者redis相關特性

 1                     Parallel.For(0, 1000000, i =>
 2                     {
 3                         Stopwatch sw1 = new Stopwatch();
 4                         sw1.Start();
 5 
 6                         if (redisHelper.GetRedisOperation().Lock(key))
 7                         {
 8                             var tt = int.Parse(redisHelper.GetRedisOperation().StringGet("calc"));
 9 
10                             tt++;
11 
12                             redisHelper.GetRedisOperation().StringSet("calc", tt.ToString());
13 
14                             redisHelper.GetRedisOperation().UnLock(key);
15                         }
16                         var v = sw1.ElapsedMilliseconds;
17                         if (v >= 10 * 1000)
18                         {
19                             Console.Write("f");
20                         }
21                         sw1.Stop();
22                     });

?

?

?


轉載請標明本文來源:http://www.cnblogs.com/yswenli/p/7421475.html?
更多內容歡迎star作者的github:https://github.com/yswenli/
如果發現本文有什么問題和任何建議,也隨時歡迎交流~

?

轉載于:https://www.cnblogs.com/yswenli/p/7421475.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252015.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252015.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252015.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

opencv-python單目視覺標定,簡單易用。

import cv2 import numpy as np import glob# 設置尋找亞像素角點的參數&#xff0c;采用的停止準則是最大循環次數30和最大誤差容限0.001 criteria (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)# 獲取標定板角點的位置 objp np.zeros((6 * 7, 3), np.f…

python多線程多進程

一、線程&進程 對于操作系統來說&#xff0c;一個任務就是一個進程&#xff08;Process&#xff09;&#xff0c;比如打開一個瀏覽器就是啟動一個瀏覽器進程&#xff0c;打開一個記事本就啟動了一個記事本進程&#xff0c;打開兩個記事本就啟動了兩個記事本進程&#xff0c…

Spring Framework 5.1.6、5.0.13 與?4.3.23 發布

開發四年只會寫業務代碼&#xff0c;分布式高并發都不會還做程序員&#xff1f; Spring Framework 5.1.6、5.0.13 與 4.3.23 發布了。 v5.1.6 包含 49 個 bug 修復和功能改進&#xff1b;v5.0.13 是 5.0.x 系列的最后一個版本&#xff0c;包含了 25 個 bug 修復和功能改進&am…

curl命令

Curl是一種支持多種協議&#xff08;http、https&#xff0c;ftp&#xff09;等&#xff0c;利用url規則在命令行下工作的文件傳輸工具&#xff0c;還支持POST、cookies、認證、從指定偏移處下載部分文件、用戶代理字符串、限速、文件大小、進度條等特征 1.語法&#xff1a; cu…

單目視覺標定:世界坐標系、相機坐標系、圖像坐標系、像素坐標系——簡單粗暴,粗暴

轉&#xff1a;https://blog.csdn.net/chentravelling/article/details/53558096 1.正文 圖像處理、立體視覺等等方向常常涉及到四個坐標系&#xff1a;世界坐標系、相機坐標系、圖像坐標系、像素坐標系。例如下圖&#xff1a; 構建世界坐標系只是為了更好的描述相機的位置在哪…

Python基礎知識-05-數據類型總結字典

python其他知識目錄 1、一道題&#xff0c;選擇商品的序號。程序員和用戶各自面對的序號起始值 如有變量 googs [汽車,飛機,火箭] 提示用戶可供選擇的商品&#xff1a; 0,汽車1,飛機2,火箭用戶輸入索引后&#xff0c;將指定商品的內容拼接打印&#xff0c;如&#xff1a;用戶輸…

Python學習筆記之異常

Python用異常對象來表示異常情況&#xff0c;如果異常對象未被處理或捕捉&#xff0c;程序就會回溯&#xff08;traceback&#xff09;中止執行。 異常可以在出錯時自動引發&#xff0c;也可以主動引發。 異常被引發后如果不被處理就會傳播至程序調用的地方&#xff0c;直到主程…

VSFTP的使用

一、基本安裝 1.安裝服務 yum -y install vsftpd //centos Redhat apt-get install vsftpd //debian ubuntu 2.開啟服務 service vsftpd status //查看狀態&#xff0c;默認是關閉的 service vsftpd start 3.開機隨操作系統啟動 chkconfig vsftpd on4.添加賬號 useradd -d /…

OC Swift混編-Swift.h File not found

https://www.jianshu.com/p/f860fe1718ca 2016.09.13 11:53* 字數 266 閱讀 1935評論 1喜歡 1今天碰到個神坑,本人項目是OC項目,最近開始使用Swift開始替代.但是,在替代的已開始就出現問題了:新建swift文件,然后提示創建bridging-Hearder文件,然后swift可以使用OC代碼了.這些都…

視覺標定,再來一波!!更簡單粗暴!!!!!!

繼續&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 一、四個坐標系簡介和轉換 相機模型為以后一切標定算法的關鍵&#xff0c;只有這邊有相當透徹的理解&#xff0c;對以后的標定算法才能有更好的理解。本人研究了好長時間&#xff0c;幾乎每天…

深入淺出NIO之Selector實現原理

2019獨角獸企業重金招聘Python工程師標準>>> 前言 Java NIO 由以下幾個核心部分組成&#xff1a; 1、Buffer 2、Channel 3、Selector Buffer和Channel在深入淺出NIO之Channel、Buffer一文中已經介紹過&#xff0c;本文主要講解NIO的Selector實現原理。 之前進行sock…

介紹一下畫圖小能手matplotlib。

我們在做完數據分析的時候需要把分析出來的結果&#xff0c;做一個圖形化的形象表達&#xff0c;這里我們就需要用到畫圖小能手matplotlib&#xff0c;下面就演示一下常用的條形圖和折線圖 散點圖 散點圖的做大的作用是研究兩個變量的相關性&#xff08;正相關&#xff0c;負相…

立體視覺標定源代碼C++,簡單粗暴!粗暴·······

疑點解答&#xff1a; 攝像機矩陣由內參矩陣和外參矩陣組成&#xff0c;對攝像機矩陣進行QR分解可以得到內參矩陣和外參矩陣。 內參包括焦距、主點、傾斜系數、畸變系數 &#xff08;1&#xff09; 其中&#xff0c;fx&#xff0c;fy為焦距&#xff0c;一般情況下&#xff…

11. 臨時表

-- 查詢5大洲國家總數 SELECT continent,COUNT(*) FROM country GROUP BY continent;-- 演示臨時表 CREATE TEMPORARY TABLE tmp_table ( continent VARCHAR(20), COUNT INT );INSERT INTO tmp_table SELECT Asia AS continent,COUNT(*) FROM country WHERE continent Asia;…

MongoDB負載信息一目了然 阿里云HDM重磅發布MongoDB監控和診斷功

2019獨角獸企業重金招聘Python工程師標準>>> 混合云數據庫管理&#xff08;HDM&#xff09;的統一監控、告警、診斷功能新增了對MongoDB的支持。 通過直觀的方式將MongoDB多個維度的負載信息統一整合&#xff0c;不僅可以清晰的查看實時負載信息&#xff0c;也可以方…

在iview的Table中添加Select(render)

首先對Render進行分析&#xff0c;在iview官方的文檔中&#xff0c;找到了table插入Button的例子&#xff1a; [javascript] view plaincopy { title: Action, key: action, width: 150, align: center, render: (h, params) > { return h(div, [ h(Butt…

JavaScript中call和apply方法

1 /*2 在js中 call和apply常用于綁定作用域3 */4 //1 簡單的綁定5 function sum(a,b){6 return ab;7 }8 //將sum的功能綁定給test2來執行9 function test2(a,b){ 10 return sum.call(this,a,b); 11 } 12 // call 和apply的區別是 apply接收數組作為參數…

工業機械人運動學正逆解,簡單粗暴!!!!!!

ur機械臂是六自由度機械臂&#xff0c;由D-H參數法確定它的運動學模型&#xff0c;連桿坐標系的建立如上圖所示。 轉動關節θi是關節變量&#xff0c;連桿偏移di是常數。 關節編號 α&#xff08;繞x軸&#xff09; a&#xff08;沿x軸&#xff09; θ&#xff08;繞z軸&am…

python opencv立體測距 立體匹配BM算法

立體標定應用標定數據轉換成深度圖標定 在開始之前&#xff0c;需要準備的當然是兩個攝相頭&#xff0c;根據你的需求將兩個攝像頭進行相對位置的固定&#xff0c;我是按平行來進行固定的&#xff08;如果為了追求兩個雙目圖像更高的生命度&#xff0c;也可以將其按一定鈍角固…

對于python 作用域新的理解

今天看Python習題&#xff0c;看到如下題目 def num():return [lambda x: i*x for i in range(4)] print([m(2) for m in num()])  # 求輸出結果是什么 我看了半天才明白這應該是一個列表生成式&#xff0c;列表中的元素為四個匿名函數&#xff0c;我本以為每個匿名函數應該是…