Android-Lua icon indicating copy to clipboard operation
Android-Lua copied to clipboard

请问应该怎么使用多线程呢?

Open qq292 opened this issue 3 years ago • 6 comments

我这样写,并没有用。。

public class FunctionThread extends JavaFunction {
    /**
     * Constructor that receives a LuaState.
     *
     * @param L LuaState object associated with this JavaFunction object
     */
    private LuaObject luaFunc;
    private LuaState luaThread;
    public FunctionThread(LuaState L) {
        super(L);
    }

    @Override
    public int execute() throws LuaException {
        if (L.isFunction(2)) {
            luaFunc = L.getLuaObject(2); 
            luaThread= L.newThread();
            luaThread.pushObjectValue(luaFunc);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    int p = luaThread.pcall(0,0,0);
                    if(p!=0){
                        Log.i("99999999999",luaThread.toString(-1));
                    }

                }
            }).start();
        }
        return 0;
    }
    public void register() {
        try {
            register("threads");
        } catch (LuaException e) {
            e.printStackTrace();
        }
    }
}

任何人都可以回答这个问题!

qq292 avatar Jan 05 '21 09:01 qq292

没看懂你的 L.newThread(); 函数是哪来的。

可以参考 demo 工程中的代码

只需把 AsyncTask 换成原生的 Thread 即可。

ichenhe avatar Jan 10 '21 12:01 ichenhe

newThread()是luastate对象的一个方法,就是复制一份原有的luastate再添加到states列表上去。用了newThread()方法,感觉是有线程的感觉了(线程函数里面放一个死循环代码,然后点击按钮,可以正常触发按钮的点击事件,不用newThread()的话,UI线程会阻塞,按钮都点不。但是死循环里面的sleep()函数还是会阻塞UI线程,按钮按得快的话,app还会直接闪退)。我是用lua调用android的api做界面。

qq292 avatar Jan 10 '21 14:01 qq292

我没注意 LuaState 有这个方法。原则上来讲 Lua 不支持多线程。 所以我的方案上在 Java 里开启一个新线程,然后在这个线程中执行 Lua 函数。 可以把 Lua 函数作为参数传递给 Java,上面提到的代码已经写的很明白了。

ichenhe avatar Jan 10 '21 14:01 ichenhe

我最开始就是你这个思路,实现的时候就有问题了。lua栈只有一个,如果java线程里面一直调用lua栈里面的一个函数,就会一直把函数和参数push到栈上。我按下按钮出发按钮点击事件的时候里面也是调用一个lua函数,这个函数和参数也会push到栈上,就和线程里面的冲突了,我估计是这样所以造成了app闪退

qq292 avatar Jan 10 '21 14:01 qq292

我大概了解了一下,LuaState 并不是线程安全的,所以我的方案有潜在风险。你的使用场景应该就触发了这种问题。

而你提到的 newThread 方法实际上是创建一个新的栈,如果把这个栈用于另一个线程,自然也就没了多线程共享栈导致的问题。但具体来讲还有许多工作要做,相关的函数包括 resume, yield, lock, unlock 等。

我没研究过 lua 多线程的问题,目测也不属于此 lib 封装的问题。这个 issue 暂时保留以供讨论。

ichenhe avatar Jan 10 '21 14:01 ichenhe

我测试了一下,newThread方法,返回的lua栈指针和原lua栈指针是一样的,也就是说newthread方法并不是深拷贝一份lua栈,所以我用了newthread还是会出现问题,用上线程锁可以解决这个问题,但是这个线程是个假的线程,因为用sleep()还是会阻塞UI线程。而且newthread方法只能用一次,用两次,也就是我想在开两个线程,app直接闪退。

还有lua函数和Java函数互相多层调用也有问题,比如:

--B开头的是Java封装的函数
--A开头的是lua函数
function A()
    B(function()
        B2()
    end
)
end

A()

Java里面是用pcall或者call方法调用。 运行的结果就是logcat缓存爆表,app进程死掉。

B(function()
    B2()
end

这样就没有问题。

qq292 avatar Jan 10 '21 22:01 qq292