var flag = threads.atomic(false); 找不到方法atomic
// 微信通知监听与模拟操作控制脚本
console.show();
// 隐藏输入框和确定按钮
ui.run(function() {
let mConsoleViewField = runtime.console.getClass().getDeclaredField('mConsoleView');
mConsoleViewField.setAccessible(true);
let refConsoleView = mConsoleViewField.get(runtime.console);
let mConsoleView = refConsoleView.get();
mConsoleView.findViewById(com.stardust.autojs.R.id.input_container).visibility = android.view.View.GONE;
});
// 文档地址 https://docs.hamibot.com/
var flag = threads.atomic(0); // 原子变量,用于线程间通信
// 监听通知的线程
threads.start(function () {
events.observeNotification();
events.on('notification', function(n) {
if (n.getPackageName() === 'com.tencent.mm') {
var text = n.getText();
log(n.getText());
log(n.getPackageName());
log(n.getTitle());
if(n.getPackageName()=="com.tencent.mm"&&n.getText().includes("小程序")){
flag.set(1); // 修改原子变量
}
}
});
});
// 模拟操作的线程
threads.start(function () {
while (true) {
if (flag.get()==1) {
log(2)
// 执行暂停后的操作
click(500, 1000);
flag.set(0); // 重置标志
}
// 正常模拟操作
gesture(1000, [100, 100], [500, 500]);
sleep(1000);
log(1)
}
}); 这两个线程如何在按下停止按钮后结束线程
回答
根据你的描述,你尝试使用 threads.atomic(false)
来创建一个原子变量,但提示找不到方法。这是因为在 Hamibot 的 threads
模块中,threads.atomic()
仅支持创建整数类型的原子变量(默认值为 0),而不能直接用于布尔值或其它类型。
如果你需要实现布尔类型的线程安全操作,可以考虑使用 ReentrantLock
或者通过封装同步机制来实现。以下是使用 ReentrantLock
实现线程安全的布尔标志示例:
// 文档地址 https://docs.hamibot.com/
var lock = threads.lock();
var flag = false;
// 设置 flag 的线程安全方法
function setFlag(value) {
lock.lock();
try {
flag = value;
} finally {
lock.unlock();
}
}
// 获取 flag 的线程安全方法
function getFlag() {
lock.lock();
try {
return flag;
} finally {
lock.unlock();
}
}
// 子线程修改 flag
threads.start(function () {
while (true) {
var current = getFlag();
log("子线程读取 flag: " + current);
setFlag(!current);
sleep(1000);
}
});
// 主线程同时读取和修改 flag
while (true) {
var current = getFlag();
log("主线程读取 flag: " + current);
setFlag(!current);
sleep(1000);
}
上面代码展示了如何用 threads.lock()
创建锁对象,并在多线程环境下对布尔变量 flag
进行安全的读写操作。
补充回答 1
要实现在线程运行时按下停止按钮结束线程,你需要:
- 创建一个 UI 停止按钮。
- 在点击按钮时设置一个标志变量为终止状态。
- 修改线程逻辑,在循环中检查该标志以决定是否退出。
以下是修改后的代码示例(文档地址 https://docs.hamibot.com/):
console.show();
// 隐藏输入框和确定按钮
ui.run(function () {
let mConsoleViewField = runtime.console.getClass().getDeclaredField('mConsoleView');
mConsoleViewField.setAccessible(true);
let refConsoleView = mConsoleViewField.get(runtime.console);
let mConsoleView = refConsoleView.get();
mConsoleView.findViewById(com.stardust.autojs.R.id.input_container).visibility = android.view.View.GONE;
});
var flag = threads.atomic(0); // 用于线程间通信的原子变量
var running = true; // 控制线程是否继续执行
// 添加一个停止按钮到界面
ui.layout(
<vertical>
<button id="stopBtn" text="停止线程"/>
</vertical>
);
// 点击事件处理
ui.stopBtn.click(function () {
running = false; // 设置running为false,触发线程退出
toast("正在停止线程...");
});
// 监听通知的线程
threads.start(function () {
events.observeNotification();
events.on('notification', function (n) {
if (n.getPackageName() === 'com.tencent.mm' && n.getText() && n.getText().includes("小程序")) {
flag.set(1); // 修改原子变量
}
});
// 循环监听直到running变为false
while (running) {
sleep(100); // 轻度休眠避免占用过高资源
}
log("通知监听线程已退出");
});
// 模拟操作的线程
threads.start(function () {
while (running) { // 当running为false时退出循环
if (flag.get() == 1) {
log(2);
click(500, 1000);
flag.set(0); // 重置标志
}
gesture(1000, [100, 100], [500, 500]);
sleep(1000);
log(1);
}
log("模拟操作线程已退出");
});
实现要点:
running
变量:这是一个布尔标志,用来控制线程是否应该继续运行。当点击按钮时将其设为false
。- 线程内循环检查:每个线程在主循环中都检查
running
的值。一旦发现running == false
,就退出循环,完成清理工作后线程自然结束。 - 日志输出提示:线程结束时会打印一条信息,帮助确认线程已正确退出。
通过这种方式可以优雅地结束两个线程,同时保持脚本的可控性和可读性。