Make policy programs really run in parallel, adding multi-threaded support to JavaScript policies at the bottom of the system

Author: The Little Dream, Created: 2023-03-02 14:19:15, Updated: 2024-03-20 15:06:41

img

Make policy programs really run in parallel, adding multi-threaded support to JavaScript policies at the bottom of the system

When developing a policy on FMZ using JavaScript, the policy architecture is consulted; if there are scenarios of concurrent design, it is passed byexchange.GoFunctions to perform concurrent calls to some interfaces, thus fulfilling the needs of some concurrent scenarios. However, it is not possible to actually create a single thread to perform a series of operations if you want to do it separately, for example, as in the Python language.threadingI'm going to do some parallel designs.

Based on this need, the FMZ platform upgraded the system underpinnings. It also added true multi-threaded support for the JavaScript language. Detailed features include:

  • Create threads to execute custom functions simultaneously.
  • This is the first time I've seen this.
  • Variables stored between shared threads.
  • Waiting for the thread to finish the recovery resource and return the execution results.
  • Forced termination of threads and recycling of resources.
  • Retrieves the current thread ID in a concurrent thread execution function.

The following article will help you understand each function individually.

Create threads to execute custom functions simultaneously

__ThreadA function can create a thread and execute a function simultaneously. For example, a concurrent function needs to be created.func1func1What does the function do? We can make it add from 0 to 9, and to see this incremental addition process, we use the for loop in func1 to pause each time (a certain number of milliseconds for the sleep function).

function func1(sleepMilliseconds) {
    var sum = 0 
    for (var i = 0 ; i < 10 ; i++) {
        sum += i 
        Sleep(sleepMilliseconds)
        Log("sum:", sum)
    }
    
    return sum
}

function main() {
    // 使用__Thread函数并发创建一个线程,参数200即为func1函数的参数,
    // 如果func1函数有多个参数,这里就具体传对应的参数
    var thread1Id = __Thread(func1, 200)
    
    // 这里需要等待线程Id为thread1Id的线程执行结果,否则main函数执行完就直接释放所有线程
    var ret = __threadJoin(thread1Id)
    Log("ret:", ret)
}

In a practical application scenario, we can run HTTP requests in parallel like this:

function main() {
    let threads = [
        "https://www.baidu.com",
        "https://www.163.com"
    ].map(function(url) {
        return __Thread(function(url) {
            Log("GET", url)
            return HttpQuery(url)
        }, url)
    })
    threads.forEach(function(tid) {
        Log(__threadJoin(tid))
    })
}

Waiting for the thread to finish executing the recovered resource and return the execution result

So in the example above, we used the last one in the main function.__threadJoinFunction to wait for concurrent thread execution to complete, variableretReceived__threadJoinThe return value of the function, which we printed, can be observed as a specific result of the execution of this concurrent string.

// id:线程ID,terminated:是否被强制停止,elapsed:耗时(纳秒),ret:线程执行函数的返回值
ret: {"id":1,"terminated":false,"elapsed":2004884301,"ret":45}

Forced termination of thread and recycling of resources

function func1(sleepMilliseconds) {
    var sum = 0 
    for (var i = 0 ; i < 10 ; i++) {
        sum += i 
        Sleep(sleepMilliseconds)
        Log("sum:", sum)
    }
    
    return sum
}

function main() {
    var thread1Id = __Thread(func1, 200)
    Sleep(1000)
    retThreadTerminate = __threadTerminate(thread1Id)
    Log(retThreadTerminate)   // true
}

Or in the example just given, after creating a thread, you can force terminate the thread after waiting 1 second.

Communication between threads

Mainly used for wireless communication__threadPostMessageFunctions and__threadPeekMessageFunctions. Let's look at the following simple example:

function func1() {
    var id = __threadId()
    while (true) {
        var postMsg = "来自id:" + id + "的线程函数func1的消息"
        __threadPostMessage(0, postMsg)              // 发送消息到主线程
        var peekMsg = __threadPeekMessage()         // 接收来自其它线程的消息
        Log(peekMsg)
        Sleep(5000)
    }
}

function main() {
    var threadId = __Thread(func1)
    
    while (true) {
        var postMsg = "来自主线程的main函数的消息"
        __threadPostMessage(threadId, postMsg)
        var peekMsg = __threadPeekMessage()
        Log(peekMsg, "#FF0000")                     // #FF0000 , 设置日志为红色用于区分
        Sleep(5000)
    }
}

__threadPostMessageA function is used to send a message to a thread, the first parameter is the ID of the specific thread to which it is sent, and the second parameter is the message sent, which can be a string, a number, an array, a JSON object, etc.

__threadPeekMessageThe function is used to listen to messages sent by a thread, and can be set to overtime (milliseconds), or set to 0 to block, and can be listened to until a message is returned.

Of course, in addition to parallel threads and main threads communicating, parallel threads can also communicate directly with each other.

Retrieve the current thread ID in a concurrent thread execution

In the example above, we usevar id = __threadId()__threadId()The function can get the ID of the current thread.

Variables stored between shared threads

In addition to communication between threads, interactions can be done using shared variables.

function testFunc() {
    __threadSetData(0, "testFunc", 100)   // 储存在当前线程环境,键值对 testFunc : 100 
    Log("testFunc执行完毕")
}

function main() {
    // threadId为1 ,创建的threadId为1的线程会先执行完,只要线程资源没有被回收,线程本地储存的变量就有效
    var testThread = __Thread(testFunc)
    
    Sleep(1000)

    // 输出 in main, get testFunc: 100
    Log("in main, get testFunc:", __threadGetData(testThread, "testFunc"))   // 取出键名为testFunc的值
}

This is a simple demonstration of all the functions.


Related

More

The bone knifeError ReferenceError: '__Thread' is not defined at main (__FILE__:5)

The bone knifeCollecting and Learning

Inventors quantifiedUpgrading the Trustee