執行緒的問題
以下是在您的 ThingWorx 應用程式中指示效能或其他穩定性問題的一些情境:
長時間存在許多阻塞的執行緒
共用資源爭用
長時間執行的執行緒
本部份提供這些類型問題的概觀。
阻塞的執行緒
許多長時間阻塞的執行緒表示在 JVM 層級上發生高資源爭用的情形或可能鎖死。當有多個執行緒阻塞,並且正在等待共用資源 (例如資料庫存取) 時,通常會防止使用者執行操作。
高爭用情形有時也會自行解決問題。例如,當大型資料庫寫入操作完成時。但是,如果執行緒在一段較長的時間內保持阻塞:
可能發生鎖死情況,亦即,執行緒會在環形模式中彼此鎖定。
或者,可能存在單一阻塞交易,並不會在需要的時間內完成處理
您可以透過下列方式檢查此問題:
搜尋已阻塞執行緒的數目。
檢查在一個快照中阻塞的執行緒是否在後續快照中保持阻塞。
下圖顯示了一個阻塞的執行緒:
在此範例中,TWEventProcessor-10 中的解壓縮操作阻塞了。它正在等待另一個解壓縮操作在 TWEventProcessor-9 執行緒中完成。有兩位使用者可能同時在 ThingWorx 中解壓縮檔案,而第二位使用者正在等待第一位使用者完成操作。這兩個操作都會存取在 TWEventProcessor-9 中鎖定的 0x2f9a4f4 物件。
如果同時也有多個事件處理器執行緒阻塞,則可能會有更大的伺服器穩定性問題。此外,事件處理子系統可能會顯示使用中執行緒數量增加。如果阻塞的情境無法盡快解決,也會顯示未處理事件的佇列正在增加。
共用資源爭用
ThingWorx 中的資料庫與事件執行緒可能會成為效能瓶頸,原因如下:
檢查 C3P0PooledConnectionPoolManagerTWEventProcessor 執行緒群組的爭用情形。大量阻塞的執行緒或在這些類別中主動工作的執行緒可能表示潛在的效能瓶頸。
如果所有資料庫與事件執行緒都被佔用,伺服器上可能會有事件排入佇列。
請考慮以下的範例。在此情況下,事件執行緒會封鎖所有資料庫連接器執行緒。呼叫堆疊中的事件執行緒 11 正在執行大型資料庫更新操作。
"C3P0PooledConnectionPoolManager[identityToken->2v1py89n68drc71w36rx7|68cba7db]-HelperThread-#7" tid=0xa0 in BLOCKED
Blocked: 414717[-1ms], Waited: 416585[-1ms]
User CPU: 5s320ms
at java.lang.Object.wait(Native Method)
- waiting on <0x56978cbf> (a com.mchange.v2.async.ThreadPoolAsynchronousRunner), held by TWEventProcessor-11
"C3P0PooledConnectionPoolManager[identityToken->2v1py89n68drc71w36rx7|68cba7db]-HelperThread-#6" tid=0x9f in BLOCKED
Blocked: 415130[-1ms], Waited: 416954[-1ms]
User CPU: 5s530ms
at java.lang.Object.wait(Native Method)
- waiting on <0x56978cbf> (a com.mchange.v2.async.ThreadPoolAsynchronousRunner), held by TWEventProcessor-11
執行操作的自訂服務邏輯可進行最佳化,如下列範例所示:
"TWEventProcessor-11" tid=0x92 in RUNNABLE
Blocked: 3913[-1ms], Waited: 37924[-1ms]
User CPU: 45s430ms
at com.thingworx.persistence.common.sql.SqlDataTableProvider.updateEntry(SqlDataTableProvider.java:13)
at com.thingworx.persistence.TransactionFactory.createDataTransactionAndReturn(TransactionFactory.java:155)
at com.thingworx.persistence.common.BaseEngine.createTransactionAndReturn(BaseEngine.java:176)
長時間執行的執行緒
長時間執行的執行緒表示 ThingWorx 應用程式中的自訂程式碼可能需要最佳化。典型使用者交易在 JVM 層級上會很快完成,通常會在一秒以內或幾秒的範圍內完成。但是,長時間執行 (例如執行 10 分鐘以上) 並且涉及自訂程式碼的執行緒就可能表示發生問題。以 10 分鐘的間隔收集數個執行緒快照,以查看操作花多少時間在特定執行緒上執行。
例如,在 60 分鐘的間隔內捕捉,會顯示相同執行緒上的相同執行模式:
http-nio-8443-exec-25" tid=0xc7 in RUNNABLE
Blocked: 750[-1ms], Waited: 8866[-1ms]
User CPU: 1h35m
- synchronizer <0x35153c2f> (a java.util.concurrent.ThreadPoolExecutor$Worker)
at com.thingworx.types.data.sorters.GenericSorter.compare(GenericSorter.java:93)
at com.thingworx.types.data.sorters.GenericSorter.compare(GenericSorter.java:20)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:360)
at java.util.TimSort.sort(TimSort.java:234)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.Collections.sort(Collections.java:175)
at com.thingworx.types.InfoTable.quickSort(InfoTable.java:722)

在此範例中,執行緒正在對資料負載執行排序。當在大型資料負載中的每個項目之間版序化時,排序操作會繼續。操作可以最佳化為在結束時發生一次。長時間執行的操作會在記憶體層級、資料庫層級或其他伺服器資源上建立爭用。因此,在自訂 ThingWorx 應用程式中識別並解決長時間執行的服務是很重要的。