threading
threading对象作为全局多线程管理工具,提供了创建并发线程、线程锁、条件对象等功能。本章节介绍threading对象的成员函数。仅JavaScript语言策略支持该对象。
Thread
Thread()函数用于创建并发线程。
Thread(func, ...args)
Thread(...items)示例
-
同时创建一个自定义函数和一个匿名函数的并发线程。
javascriptfunction test1(a, b, c) { Log("test1:", a, b, c) } function main() { var t1 = threading.Thread(test1, 1, 2, 3) var t2 = threading.Thread(function (msg) { Log("msg:", msg) }, "Hello thread2") t1.join() t2.join() } -
使用
Thread(...items)形式创建并发线程,按顺序执行多个函数。javascriptfunction test1(msg) { Log("msg:", msg) test2("Hello test2") } function main() { var t1 = threading.Thread( [function(a, b, c) {Log(a, b, c)}, 1, 2, 3], [test1, "Hello test1"], [`function test2(msg) {Log("msg:", msg)}`]) t1.join() } -
支持向并发执行函数的参数中传入函数。
javascriptfunction testFunc1(p) { Log("testFunc1 p:", p) } function main() { threading.Thread(function(pfn) { var threadName = threading.currentThread().name() var threadId = threading.currentThread().id() pfn(`in thread threadName: ${threadName}, threadId: ${threadId}`) }, testFunc1).join() } -
支持传入函数字符串,可动态导入外部库进行并发计算。
javascriptfunction ml(input) { const net = new brain.NeuralNetwork() net.train([ { input: [0, 0], output: [0] }, { input: [0, 1], output: [1] }, { input: [1, 0], output: [1] }, { input: [1, 1], output: [0] }, ]) return net.run(input) } function main() { var ret = threading.Thread([ml, [1, 0]], [HttpQuery("https://unpkg.com/brain.js")]).join() // ret: {"id":1,"terminated":false,"elapsed":337636000,"ret":{"0":0.9339330196380615}} Log(ret) }
返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
func | function | 是 | 参数 |
arg | string / number / bool / object / array / function / any (系统支持的所有类型) | 否 | 参数 |
item | array | 是 | 参数 |
参考
备注
传入Thread()函数用于并发执行的线程函数func运行在隔离环境中,因此无法直接引用线程外部的变量,引用时会导致编译失败。同时,线程内不支持引用其他闭包函数。线程内部可以调用平台提供的所有API,但不能调用用户自定义的其他函数。
当线程执行完毕且没有被持续引用时,系统底层会自动回收线程相关的资源,无需显式调用join()函数来释放资源。如果存在持续引用导致无法释放资源,当并发数量超过2000个时会报错:InternalError: too many routine wait, max is 2000。
支持回测系统、实盘环境。所有并发线程相关的函数在回测系统中仅作为代码兼容性支持,实际不会真正执行并发线程,本章不再赘述。
getThread
getThread()函数用于根据指定的线程ID获取线程对象。
getThread(threadId)示例
通过threadId获取指定的线程对象。
javascript
function main() {
var t1 = threading.Thread(function () {
// Thread 对象有方法:id(),用于获取线程的Id,可以查看文档对应Thread对象的章节
var id = threading.currentThread().id()
var thread1 = threading.getThread(id)
Log("id:", id, ", thread1.id():", thread1.id())
Log(`id == thread1.id():`, id == thread1.id())
})
t1.join()
}返回值
| 类型 | 描述 |
|
|
参数
| 名称 | 类型 | 必填 | 描述 |
threadId | number | 是 | 参数 |
参考
备注
支持回测系统、实盘环境。
如果目标线程已经执行完毕并被释放,则无法通过threading.getThread(threadId)获取该线程的线程对象。
mainThread
mainThread()函数用于获取主线程的线程对象,即策略中main()函数所在的线程。
mainThread()示例
-
获取主线程的
Thread对象,输出主线程的threadId。javascriptfunction main() { Log("主线程的threadId:", threading.mainThread().id()) } -
在并发线程中获取主线程的线程对象。
javascriptfunction test() { Log("test函数中输出主线程Id:", threading.mainThread().id()) } function main() { var t1 = threading.Thread(test) t1.join() }
返回值
| 类型 | 描述 |
|
|
参考
备注
支持回测系统、实盘环境。
currentThread
currentThread()函数用于获取当前线程的线程对象。
currentThread()示例
获取当前线程的Thread对象,输出当前线程的threadId。
javascript
function test() {
Log("当前线程的Id:", threading.currentThread().id())
}
function main() {
var t1 = threading.Thread(test)
t1.join()
}返回值
| 类型 | 描述 |
|
|
参考
备注
支持回测系统、实盘环境。
Lock
Lock()函数用于创建线程锁对象。
Lock()示例
两个并发线程访问共享资源。
javascript
function consumer(productionQuantity, dict, lock) {
for (var i = 0; i < productionQuantity; i++) {
lock.acquire()
var count = dict.get("count")
Log("consumer:", count)
Sleep(1000)
lock.release()
}
}
function producer(productionQuantity, dict, lock) {
for (var i = 0; i < productionQuantity; i++) {
lock.acquire()
dict.set("count", i)
Log("producer:", i)
Sleep(1000)
lock.release()
}
}
function main() {
var dict = threading.Dict()
dict.set("count", -1)
var lock = threading.Lock()
var productionQuantity = 10
var producerThread = threading.Thread(producer, productionQuantity, dict, lock)
var consumerThread = threading.Thread(consumer, productionQuantity, dict, lock)
consumerThread.join()
producerThread.join()
}返回值
| 类型 | 描述 |
|
|
参考
备注
支持回测系统、实盘环境。
Condition
Condition()函数用于创建条件变量对象,该对象在多线程并发环境中实现线程间的同步与通信。通过Condition(),线程可以在特定条件未满足时进入等待状态,直到其他线程发出条件满足的通知。
Condition()示例
两个并发线程访问共享资源。
javascript
function consumer(productionQuantity, dict, condition) {
for (var i = 0; i < productionQuantity; i++) {
condition.acquire()
while (dict.get("array").length == 0) {
condition.wait()
}
var arr = dict.get("array")
var count = arr.shift()
dict.set("array", arr)
Log("consumer:", count, ", array:", arr)
condition.release()
Sleep(1000)
}
}
function producer(productionQuantity, dict, condition) {
for (var i = 0; i < productionQuantity; i++) {
condition.acquire()
var arr = dict.get("array")
arr.push(i)
dict.set("array", arr)
Log("producer:", i, ", array:", arr)
condition.notify()
condition.release()
Sleep(1000)
}
}
function main() {
var dict = threading.Dict()
dict.set("array", [])
var condition = threading.Condition()
var productionQuantity = 10
var producerThread = threading.Thread(producer, productionQuantity, dict, condition)
var consumerThread = threading.Thread(consumer, productionQuantity, dict, condition)
consumerThread.join()
producerThread.join()
}返回值
| 类型 | 描述 |
|
|
参考
备注
回测系统暂不支持此功能,仅提供接口定义。
Event
Event()函数用于创建一个线程事件对象,该对象用于线程间的同步,允许一个线程等待另一个线程的通知或信号。
Event()示例
两个并发线程访问共享资源。
javascript
function consumer(productionQuantity, dict, pEvent, cEvent) {
for (var i = 0; i < productionQuantity; i++) {
while (dict.get("array").length == 0) {
pEvent.wait()
}
if (pEvent.isSet()) {
pEvent.clear()
}
var arr = dict.get("array")
var count = arr.shift()
dict.set("array", arr)
Log("consumer:", count, ", array:", arr)
cEvent.set()
Sleep(1000)
}
}
function producer(productionQuantity, dict, pEvent, cEvent) {
for (var i = 0; i < productionQuantity; i++) {
while (dict.get("array").length != 0) {
cEvent.wait()
}
if (cEvent.isSet()) {
cEvent.clear()
}
var arr = dict.get("array")
arr.push(i)
dict.set("array", arr)
Log("producer:", i, ", array:", arr)
pEvent.set()
Sleep(1000)
}
}
function main() {
var dict = threading.Dict()
dict.set("array", [])
var pEvent = threading.Event()
var cEvent = threading.Event()
var productionQuantity = 10
var producerThread = threading.Thread(producer, productionQuantity, dict, pEvent, cEvent)
var consumerThread = threading.Thread(consumer, productionQuantity, dict, pEvent, cEvent)
consumerThread.join()
producerThread.join()
}返回值
| 类型 | 描述 |
|
|
参考
备注
支持回测系统、实盘环境。
Dict
Dict()函数用于创建一个字典对象,用于在并发线程间传递数据。
Dict()示例
-
向并发线程执行函数传入普通对象,测试修改对象键值后是否会影响其他线程中的对象键值。
javascriptfunction threadFun1(obj) { obj["age"] = 100 while (true) { Log("threadFun1 obj:", obj) Sleep(5000) } } function threadFun2(obj) { while (true) { Log("threadFun2 obj:", obj) Sleep(5000) } } function main() { var obj = {"age": 10} var t1 = threading.Thread(threadFun1, obj) var t2 = threading.Thread(threadFun2, obj) t1.join() t2.join() } -
向并发线程执行函数传入
Dict()函数创建的ThreadDict对象,测试修改对象键值后是否会影响其他线程中的对象键值。javascriptfunction threadFun1(threadDict) { threadDict.set("age", 100) while (true) { Log(`threadFun1 threadDict.get("age"):`, threadDict.get("age")) Sleep(5000) } } function threadFun2(threadDict) { while (true) { Log(`threadFun2 threadDict.get("age"):`, threadDict.get("age")) Sleep(5000) } } function main() { var threadDict = threading.Dict() threadDict.set("age", 10) var t1 = threading.Thread(threadFun1, threadDict) var t2 = threading.Thread(threadFun2, threadDict) t1.join() t2.join() }
返回值
| 类型 | 描述 |
|
|
参考
备注
向并发线程函数传入普通对象时采用深拷贝方式传递,在并发线程中修改键值不会影响其他线程中的字典。
支持回测系统、实盘环境。
pending
pending函数用于获取当前策略程序中正在运行的并发线程数量。
pending()示例
创建两个并发运行的线程,并在不同时间点调用pending()函数。
javascript
function threadFun1() {
Log("threadFun1")
Sleep(3000)
}
function threadFun2() {
for (var i = 0; i < 3; i++) {
LogStatus(_D(), "print from threadFun2")
Sleep(3000)
}
}
function main() {
Log(`begin -- threading.pending():`, threading.pending())
var t1 = threading.Thread(threadFun1)
var t2 = threading.Thread(threadFun2)
Log(`after threading.Thread -- threading.pending():`, threading.pending())
t1.join()
t2.join()
Log(`after thread.join -- threading.pending():`, threading.pending())
}返回值
| 类型 | 描述 |
number |
|
参考
备注
当策略main()函数开始运行时直接调用pending()函数将返回1,这是因为策略main()函数所在的主线程本身也被计入正在运行的线程中。
支持回测系统和实盘环境。