জাভাস্ক্রিপ্ট নীতি নকশায় _Thread ফাংশন প্রয়োগ

লেখক:ছোট্ট স্বপ্ন, সৃষ্টিঃ ২০২৩-০৭-০৪ ১৬ঃ৩৫ঃ৪২, আপডেটঃ ২০২৩-০৯-১৮ ১৯ঃ৩২ঃ৫১

img

জাভাস্ক্রিপ্ট নীতি নকশায় _Thread ফাংশন প্রয়োগ

প্রাথমিক এফএমজেড নীতির নকশায়, অ্যাসিনক্রোনাস সমান্তরাল অপারেশনগুলি কেবলমাত্র যদি প্রয়োজন হয় তবে ব্যবহার করা যেতে পারেexchange.Go()FMZ প্যাকেজিং ইন্টারফেসের সমান্তরালীকরণ বাস্তবায়নের জন্য ফাংশনগুলি একসাথে কিছু কাস্টমাইজড ক্রিয়াকলাপ (ফাংশন) সম্পাদন করতে পারে না। যদিও এই নকশাটি কৌশল প্রোগ্রামগুলি কার্যকর করার জন্য দক্ষতা বৃদ্ধি করে, তবে স্থানীয় প্রোগ্রামিং ভাষায় সমান্তরাল নকশার অভিজ্ঞতা অর্জনকারী সহপাঠীদের জন্য সাধারণ অনুভূতি খুব অস্বাভাবিক।

এফএমজেড-এর নতুন সহপাঠীরাও বুঝতে পারছে না।exchange.Go()ফাংশন ব্যবহার, ব্যবহারexchange.Go()এটি এখনও ক্রমাগত সম্পাদিত কোডের মধ্যে একের পর এক এক্সিকিউশন স্ট্রিং বলে মনে হচ্ছে। সুতরাং এই নিবন্ধে আমরা FMZ প্ল্যাটফর্মের নতুন সমান্তরাল থ্রেড বৈশিষ্ট্যগুলি নিয়ে আলোচনা করবঃ__Thread()ইত্যাদি সিরিজ ফাংশনের ব্যবহার এবং কৌশলগত পদ্ধতির অস্বাভাবিক নকশা।

১, সহজ সমান্তরাল নকশা

যদি আমরা চাই যে নীতির মূল থ্রেডটি একই সাথে চালিত হয় এবং আমরা যে কাস্টম ফাংশনটি লিখেছি তা চালানোর জন্য একটি সাবথ্রেড চালিত হয়, তবে আমরা নিম্নলিখিত কোডের অনুরূপ নকশা ব্যবহার করতে পারি। নীতির কোডে একটি ফাংশন কাস্টমাইজ করুনGetTickerAsync(), এই ফাংশনের নির্দিষ্ট ফাংশন লিখুন. এই ফাংশনটি একটি মৃত চক্র সম্পাদন করে, এই ফাংশনেwhileএফএমজেড-এর এপিআই ইন্টারফেস, যা ঘূর্ণায়মানভাবে কল করা হয়ঃGetTicker()এই ভিডিওতে, আপনি আপনার গ্রাহকের সাথে যোগাযোগ করতে পারেন।

তারপর ব্যবহার করুন।__threadSetData(0, "ticker", t)এটি মূল স্ট্রিং-এ একটি ডেটা লিখবে।tickerএর মান হলtঅর্থাৎGetTicker()এর রিটার্ন ভ্যালু হলো

__threadSetData(0, "ticker", t)

আমরা একটি কাস্টম ফাংশন ডিজাইন করেছি যা একই সাথে কাজ করে, আমরা এটি লিখতে পারি।main()ফাংশনের কোড,main()ফাংশনটি শুরু করার জন্য, আমরা ব্যবহার করিঃ

__Thread(GetTickerAsync, 0)   // GetTickerAsync为需要并发执行的自定义函数,0为这个传入GetTickerAsync函数的参数

একটি সমান্তরাল থ্রেড তৈরি করুন, এবং এই থ্রেডটি শুরু হবেGetTickerAsync()ফাংশন.main()ফাংশনটি তার নিজের কাজ শুরু করে।whileআবর্তন, আবর্তনের মধ্যে গ্রহণGetTickerAsync()ফাংশনটি আপডেট করা ডেটা মুদ্রণ করেঃ

var t = __threadGetData(0, "ticker")
Log(t)

সম্পূর্ণ কোড উদাহরণঃ

function GetTickerAsync(index) {
    while (true) {
        var t = exchanges[index].GetTicker()
        __threadSetData(0, "ticker", t)
        Sleep(500)
    }
}

function main() {
    __Thread(GetTickerAsync, 0)

    while(true) {
        var t = __threadGetData(0, "ticker")
        Log(t)
        Sleep(1000)
    }
}

রিয়েল ডিস্ক চালানোর পরীক্ষাঃ

img

এটি একটি সহজ অ্যাপ্লিকেশন ডিজাইন, এবং আমরা অন্যান্য চাহিদা নকশা দেখতে হবে।

২। একক নকশা

আপনি একটি ফাংশন ডিজাইন করতে পারেন যাতে 10 টি থ্রেড একসাথে তৈরি করা যায়, প্রতিটি থ্রেড একটি নিম্নলিখিত অপারেশন ফাংশন সম্পাদন করে।main()একটি ফাংশন ডিজাইন করুনwhileলুপ, সনাক্তকরণ কৌশল ইন্টারঅ্যাকশন নির্দেশ।placeMultipleOrdersআমরা এই একক ফাংশনটি কল করতে চাই।testPlaceMultipleOrders()

if (cmd == "placeMultipleOrders") {
    // ...
}

নীতি সম্পাদনা পৃষ্ঠায় নীতি ইন্টারঅ্যাকশন ডিজাইন যুক্ত করুন, একটি বোতাম সেট করুন, কমান্ডঃ placeMultipleOrders

img

সম্পূর্ণ কোড উদাহরণঃ

function placeOrder(exIndex, type, price, amount) {
    var id = null 
    if (type == "Buy") {
        id = exchanges[exIndex].Buy(price, amount)
    } else if (type == "Sell") {
        id = exchanges[exIndex].Sell(price, amount)
    } else {
        throw "type error! type:" + type
    }
}

function testPlaceMultipleOrders(index, beginPrice, endPrice, step, type, amount) {
    Log("beginPrice:", beginPrice, ", endPrice:", endPrice, ", step:", step, ", type:", type, ", amount:", amount)
    var tids = []
    for (var p = beginPrice; p <= endPrice; p += step) {
        var tid = __Thread(placeOrder, index, type, p, amount)
        tids.push(tid)
        Sleep(10)
    }
    Sleep(1000)
    for (var i = 0; i < tids.length; i++) {
        __threadTerminate(tids[i])
    }
}

function main() {
    while(true) {
        LogStatus(_D())
        var cmd = GetCommand()
        if (cmd) {
            if (cmd == "placeMultipleOrders") {
                var t = _C(exchange.GetTicker)
                var beginPrice = t.Last * 0.8
                var endPrice = t.Last * 0.9
                var step = t.Last * 0.01
                testPlaceMultipleOrders(0, beginPrice, endPrice, step, "Buy", 0.01)
                var orders = exchange.GetOrders()
                for (var i = 0; i < orders.length; i++) {
                    Log(orders[i])
                }
            }
        }
        Sleep(1000)
    }
}
  • টেস্টিং পদ্ধতিটি হাউজিং তালিকা ব্যবহার করে, বর্তমান মূল্যের 80% ~ 90% থেকে ক্রমবর্ধমান, অ্যানালগ ডিস্ক পরিবেশ পরীক্ষা ব্যবহার করে, ইন্টারঅ্যাকশন বোতামটি ক্লিক করে টেস্টটি ট্রিগার করুনঃ

    img

  • "placeMultipleOrders" বোতামটি ক্লিক করার পরে, একটি বার্তা অনুরোধ করা হয়ঃ

    img

  • নীতির লোগোটি দেখায় যে আপনি একই সময়ে একটি অপারেশন চালাচ্ছেনঃ

    img

৩। সমান্তরাল থ্রেড এক্সিকিউশন ফাংশনে ওয়েবসকেট সংযোগ তৈরি করুন

এই অনুরোধটি একজন FMZ ব্যবহারকারীর দ্বারা করা হয়েছিল, যিনি আশা করেছিলেন যে একটি সহজ উদাহরণ প্রদর্শন করা হবে কিভাবে এটিকে সমান্তরাল থ্রেডে ব্যবহার করা যায়।ওয়েবসকেটএটি আমাদেরকে একটি মেইন থ্রেডের সাথে সংযোগ স্থাপন করতে এবং কীভাবে ডেটা প্রেরণ করা যায় তা ডিজাইন করতে সহায়তা করে।main()ফাংশন ।

আসলে এটি খুবই সহজ, এবং পূর্ববর্তী উদাহরণে একই সময়ে থ্রেড তৈরি করার মতোই।__threadPeekMessage()ফাংশন এবং__threadPostMessage()ফাংশন. বিএনএ এক্সচেঞ্জের ওয়েবসকেট এপিআই ইন্টারফেস কলের উদাহরণ হিসাবে, আমরা ডিজাইনে ওয়েবসকেট সংযোগ বন্ধ করার জন্যও মনোযোগ দিতে হবে। নিম্নলিখিত উদাহরণে দেখানো হয়েছে কিভাবে একটি সমান্তরাল থ্রেডকে জানানো হয় এবং এটি বন্ধ করা হয়।

সম্পূর্ণ কোড উদাহরণঃ

var tid = null 

function createWS() {
    // wss://stream.binance.com:9443/ws/<streamName> , <symbol>@ticker
    
    var stream = "wss://stream.binance.com:9443/ws/btcusdt@ticker"    
    var ws = Dial(stream)
    Log("创建WS连接:", stream)
    
    while (true) {
        var data = ws.read()
        if (data) {            
            __threadPostMessage(0, data)
        }
        Log("接收到WS链接推送的数据,data:", data)
        
        // __threadPeekMessage 超时参数设置-1,不阻塞
        var msg = __threadPeekMessage(-1)
        if (msg) {
            if (msg == "stop") {
                Log("并发线程Id:", __threadId(), "接收到stop指令")
                break
            }
        }
    }

    Log("并发线程执行完毕,关闭ws连接")
    ws.close()
}

function main() {
    tid = __Thread(createWS)
    Log("创建并发线程,线程Id:", tid)

    while(true) {
        // __threadPeekMessage 的超时参数设置为0,阻塞等待数据
        var data = __threadPeekMessage(0)
        Log("接收到并发线程", ", Id:", tid, ", 发送的数据,data:", data, "#FF0000")
        
        var tbl = {
            type : "table", 
            title : "<symbol>@ticker频道推送消息",
            cols : ["事件类型", "事件时间", "交易对", "24小时价格变化", "24小时价格变化百分比", "平均价格", "最新成交价格", "24小时内成交量", "24小时内成交额"],
            rows : []
        }

        try {
            data = JSON.parse(data)
            tbl.rows.push([data.e, _D(data.E), data.s, data.p, data.P, data.w, data.c, data.v, data.q])
        } catch (e) {
            Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
        }
        LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`")
    }
}

function onexit() {
    Log("扫尾函数,向Id为", tid, "的并发线程发送stop指令")
    __threadPostMessage(tid, "stop")
    Log("等待Id为", tid, "的并发线程停止")
    __threadJoin(tid)
    Log("扫尾函数执行完毕")
}

রিয়েল ডিস্ক চালানোর পরীক্ষাঃ

img

আপনি দেখতে পাচ্ছেনmain()ফাংশনটি ধারাবাহিকভাবে ওয়েবসকেট সংযোগ থেকে প্রাপ্ত ট্রেডিং ডেটা গ্রহণ করে।

যখন আপনি একটি বাস্তব প্লেট নীতি বন্ধ করেন, তখন স্কেভিং ফাংশনটি কাজ শুরু করেঃ

img


সম্পর্কিত

আরো

স্পার্ডা খেলুনশেষ উদাহরণ, যদি অনেকগুলি ws থ্রেড থাকে এবং একাধিক বিষয় সাবস্ক্রাইব করা থাকে, তাহলে থ্রেডের মধ্যে যোগাযোগের ক্ষেত্রে, get/set পদ্ধতি বা peek/post পদ্ধতি ব্যবহার করে কোনটি ভাল পারফরম্যান্স করবে?

স্পার্ডা খেলুনথ্রেডের মধ্যে শেয়ার করা ভেরিয়েবলের অন্তর্নিহিত বাস্তবায়নটি রেফারেন্স ভেরিয়েবলকে সমর্থন করে না এবং প্রতিবার আপডেট করার সময় পুনরায় সেট করতে হয়, যা খুব কম দক্ষ।

ছোট্ট স্বপ্নএই দুইটি পদ্ধতির মধ্যে কোন পার্থক্য নেই, সবই সম্ভব।