Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
qq292 opened this issue Jan 5, 2021 · 6 comments
Open

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

qq292 opened this issue Jan 5, 2021 · 6 comments
Labels

Comments

@qq292
Copy link

qq292 commented Jan 5, 2021

我这样写,并没有用。。

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();
        }
    }
}

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

@ichenhe
Copy link
Owner

ichenhe commented Jan 10, 2021

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

可以参考 demo 工程中的代码

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

@qq292
Copy link
Author

qq292 commented Jan 10, 2021

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

@ichenhe
Copy link
Owner

ichenhe commented Jan 10, 2021

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

@qq292
Copy link
Author

qq292 commented Jan 10, 2021

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

@ichenhe
Copy link
Owner

ichenhe commented Jan 10, 2021

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

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

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

@qq292
Copy link
Author

qq292 commented Jan 10, 2021

我测试了一下,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

这样就没有问题。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants