线程问题
以下是一些在 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 级别 (在 1 秒内或几秒内) 快速完成。但是,运行时间过长 (例如,已运行 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 应用程序中标识和处理运行时间过长的服务非常重要。