本书标签: 游戏同人 

第19节:多线程执行

原神第二课堂:胡桃讲编程之JS

各位往生堂的小弟子、MC 的红石建筑师们,嘿嘿,欢迎回到胡堂主的第二课堂!上节课咱们打通了 JS 调用 Java 的跨语言通道,今天咱们要解锁 JS 的「多线程执行」神技 —— 这就好比往生堂同时开多个业务窗口,伙计们分头烧符纸、整理档案,再也不用让客户排队;MC 里同时跑多个红石电路,自动刷石机、刷怪塔后台并行,再也不会卡玩家操作!咱们用原神 + 我的世界双线类比,严格遵循 ECMAScript-262 标准,把知识点讲透,小白也能秒懂!

一、核心原理:双线类比讲透多线程

首先明确核心:ECMAScript-262 标准规定 JS 是单线程事件循环模型,就像往生堂原本只有堂主一个人办业务,一次只能处理一个客户;而 Java 的java.lang.Thread就像给往生堂招了伙计、给 MC 加了红石调度器,让 JS 代码能同时跑多个任务,绕开单线程限制!

原神线类比

往生堂的「主线程」是堂主亲自处理的 VIP 业务(比如给钟离办业务),必须按顺序来,不能插队;「多线程」就是开多个独立窗口:A 伙计烧符纸、B 伙计整理档案、C 伙计接待散客,同时开工互不干扰,就算烧符纸耗时久,也不会耽误其他业务,效率直接拉满!

MC 线类比

MC 的「主线程」是游戏核心渲染线程,负责玩家操作、画面刷新,是世界的 “主心骨”;「多线程」就是加多个后台红石调度器:自动刷石机、刷怪塔、农场在后台并行运算,就算后台任务多,也不会卡玩家操作,真正实现 “玩着刷资源” 的爽感!

底层机制(ECMA-262 适配)

JS 单线程是标准规定,但 ECMA-262 允许宿主环境(如 Android)扩展能力,咱们通过 JavaThread给 JS 创建子线程,把 JS 任务放到子线程执行,实现并行。简单说:JS 是单线程的 “堂主”,Java Thread 是多线程的 “伙计”,让伙计帮堂主干活,完全符合标准规范!

二、实操代码:双线并行,标准语法落地

全程严格遵循 ECMAScript-262 标准,分 Java 层(调度台)和 JS 层(业务代码),衔接上一节的 UI 线程知识点:

Java 层(多线程调度桥接)

这是「往生堂伙计调度台」「MC 红石调度器」,用java.lang.Thread创建子线程,加线程安全处理:

java

运行

import android.app.Activity;

import android.os.Handler;

import android.os.Looper;

import android.webkit.WebView;

import android.widget.Toast;

public class JsThreadBridge {

private final Activity mActivity;

private final WebView mWebView;

// 主线程Handler,呼应上一节runOnUiThread

private final Handler mMainHandler = new Handler(Looper.getMainLooper());

public JsThreadBridge(Activity activity, WebView webView) {

mActivity = activity;

mWebView = webView;

}

// 核心方法:子线程执行JS

@android.webkit.JavascriptInterface

public void runJsInThread(String jsCode) {

new Thread(() -> mWebView.evaluateJavascript(jsCode, null)).start();

}

// 线程安全弹窗(子线程切UI线程)

@android.webkit.JavascriptInterface

public void showSafeToast(String msg) {

mMainHandler.post(() -> Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show());

}

// 同步锁:解决多线程资源竞争(档案锁/红石锁存器)

private int mTotalBusiness = 0;

@android.webkit.JavascriptInterface

public synchronized void addBusiness(int count) {

mTotalBusiness += count;

showSafeToast("往生堂总业务量:" + mTotalBusiness);

}

}

JS 层(双线并行业务代码)

开启严格模式,用标准 ECMA-262 语法,编写原神、MC 两条线的多线程任务:

javascript

运行

"use strict"; // 符合ECMA-262标准的严格模式

// 获取Java注入的桥接对象

const HutaoThreadBridge = window.HutaoThreadBridge;

// 原神线:多线程业务

const burnTalisman = `(function() {

let count = 0;

for(let i = 0; i < 100; i++) count++;

HutaoThreadBridge.addBusiness(count);

HutaoThreadBridge.showSafeToast("【往生堂】符纸烧完!共" + count + "张");

})();`;

const sortArchive = `(function() {

let archives = ["旅行者", "钟离", "刻晴", "胡桃"];

archives.sort();

HutaoThreadBridge.addBusiness(archives.length);

HutaoThreadBridge.showSafeToast("【往生堂】档案整理完!共" + archives.length + "份");

})();`;

// MC线:多线程红石运算

const autoStone = `(function() {

let stone = 0;

for(let i = 0; i < 200; i++) stone += 2;

HutaoThreadBridge.showSafeToast("【MC】刷石机每小时产石:" + stone + "个");

})();`;

// 启动所有多线程任务,同时执行

HutaoThreadBridge.runJsInThread(burnTalisman);

HutaoThreadBridge.runJsInThread(sortArchive);

HutaoThreadBridge.runJsInThread(autoStone);

三、核心注意事项与总结

关键避坑指南

UI 线程安全:子线程不能直接操作 UI,就像伙计不能改堂主的 VIP 业务单,必须用runOnUiThread切回主线程,否则会崩溃;

资源竞争:多个线程同时修改共享变量(如总业务量),会出现数据错误,必须用synchronized同步锁,保证一次只有一个线程修改;

避免耗时过长:不要让子线程任务太耗时,避免占用系统资源,影响主线程。

知识点总结

JS 本身单线程(ECMA-262 标准),靠 JavaThread实现多线程并行;

原神类比:多线程 = 往生堂多业务窗口并行,MC 类比:多线程 = 多红石电路后台并行;

核心要求:线程安全、同步锁、符合 ECMA-262 标准语法。

四、课后练习题(双线实操)

基础题(必做)

编写 Java 桥接类JsThreadBridge,实现runJsInThread方法,用java.lang.Thread启动子线程。

编写符合 ECMA-262 标准的 JS 代码,定义主线程、子线程两个任务,分别打印「往生堂主线程业务」「往生堂子线程业务」,观察并行效果。

测试运行,确保两个任务互不干扰。

进阶题(选做)

在 Java 类中添加共享变量mRedstoneCount,写addRedstoneCount方法,先不加synchronized,用两个子线程同时调用,观察数据错误;

加synchronized后再次测试,验证同步锁的作用;

启动 10 个线程调用,验证线程安全。

综合题(挑战)

结合上一节的调用 Java、UI 线程,编写完整 demo:Java 层实现多线程桥接,JS 层分原神、MC 线,同时启动 5 个线程统计业务量和红石数量,用同步锁保证数据正确,子线程计算、主线程更新 UI,严格符合 ECMA-262 标准。

嘿嘿,今天的课就到这里啦!多线程就是给 JS 开了外挂,让原本单线程的代码效率拉满,下次咱们讲「在 UI 线程执行」,把线程安全彻底讲透,大家记得准时来上课哦!