Table of Contents

Thread(线程) API

Thread(线程) API为OpenOS提供了协程的一种变体。线程比基础的协程在很多方面都更高级,并且对很多工作流程而言都更易用。OpenOS线程是自主的,非阻塞的,可分离的进程。

独立事件注册

每个线程都维护了一套独立的事件注册机制;不继承也不分享。线程中创建的所有事件注册记录(即侦听器或定时器)都只从属于此线程。

概述

线程主要有两种用途是其他选择无法提供:

函数

此处定义了两类API。

  1. 线程API,或者说静态函数,由require("thread")提供。
  2. 线程句柄API,或者说适用于thread.create创建的线程对象的api。在此文档中这些线程句柄将会仅以t表示。

线程API

snippet.lua
local thread = require("thread")
print("Main program start")
thread.create(function(a, b)
  print(a)
  os.sleep()
  print(b)
end, 'A', 'B')
print("Main program end")

输出:

Main program start
A
Main program end
B
snippet.lua
local thread = require("thread")
print("Main program start")
local t = thread.create(function(a, b)
  print(a)
  os.sleep()
  print(b)
end, 'A', 'B')
thread.waitForAll({t})
print("Main program end")

输出:

Main program start
A
B
Main program end
snippet.lua
local thread = require("thread")
print("Main program start")
local t1 = thread.create(function(a, b)
  print(a)
  os.sleep()
  print(b)
end, 'A', 'B')
local t2 = thread.create(function(c, d)
  print(c)
  os.sleep()
  os.sleep()
  print(d)
end, 'C', 'D')
thread.waitForAny({t1, t2})
print("Main program end")

输出:

Main program start
A
C
B
Main program end
D

请注意线程恢复的顺序并未指定,此样例中也有可能在输出“Main program end”之前就输出“D”。

线程句柄API

t:resumet:suspend的特别注释

不要把这两个方法当作coroutine.resume()coroutine.yield()。这两个方法是间接的,而且线程是独自异步开始或停止运行的。请将这一特性与协程方法相对比,协程方法是直接的,而且会立即唤起或离开协程的执行。参考这些样例:

snippet.lua
local thread = require("thread")
local t -- 此样例需要t的upvalue
t = thread.create(function()
  print("start")
  thread.current():suspend()
  print("after suspend")
  os.sleep()
  print("after sleep")
end)

输出:

start
snippet.lua
local thread = require("thread")
local t -- this example needs an upvalue to t
t = thread.create(function()
  print("start")
  thread.current():suspend()
  print("after suspend")
  os.sleep()
  print("after sleep")
end)
print("outside thread create")
t:resume()
print("after resume")

输出:

start
outside thread create
after suspend
after resume
after sleep
snippet.lua
local thread = require("thread")
local t = thread.create(function()
  while true do
    print("running")
    print("still running")
    os.sleep()
    print("after sleep")
  end
  print("unreachable code")
end)
print("before kill")
t:kill()
print("after kill")

输出:

running
still running
before kill
after kill

状态样例

snippet.lua
local thread = require("thread")
local t = thread.create(function()
  print("before sleep")
  os.sleep()
  print("after sleep")
end)
print(t:status())

输出:

before sleep
running
after sleep
snippet.lua
local thread = require("thread")
local t = thread.create(function()
  print("before sleep")
  os.sleep()
  print("after sleep")
end)
t:suspend()
print(t:status())
os.sleep(10)
print(t:status())
t:resume()
print("after resume")
print(t:status())

输出:

before sleep
suspended
suspended
after resume
dead
snippet.lua
local detached_thread = thread.create(function() end):detach()

线程异常样例

此样例演示了线程抛出异常时会发生什么。线程在抛出未捕获的异常时会停止执行并进入“死亡”状态。报错信息将不会输出到stdout或stderr(详见t:resume())。

snippet.lua
local thread = require("thread")
local tty = require("tty")
 
print("p start")
local reader = thread.create(function()
  print("reader start")
  error("thread abort") -- 抛出一个异常
  print("reader done")
end)
print("p end", reader:status())

输出:

p start
reader start
p end	dead

线程中断处理函数样例

此样例演示了你该如何注册处理软中断(^c)的函数,用于关闭文件句柄、释放资源等等,然后退出整个程序。

snippet.lua
local thread = require("thread")
local event = require("event")
 
local cleanup_thread = thread.create(function()
  event.pull("interrupted")
  print("cleaning up resources")
end)
 
local main_thread = thread.create(function()
  print("main program")
  while true do
    io.write("input: ")
    io.read()
  end
end)
 
thread.waitForAny({cleanup_thread, main_thread})
os.exit(0) -- 关闭所有剩余线程

假设用户按下了^c发送了一次软中断

输出:

main program
input: ^c
cleaning up resources

非阻塞式线程Yield/Pull操作样例

此样例演示了现在OpenOS可支持非阻塞式线程。

snippet.lua
local event = require("event")
local thread = require("thread")
thread.create(function()
  a,b,c,d,e,f,g = coroutine.yield()
  print(a,b,c,d,e,f,g)
  print(event.pull())
end)
 
event.push("custom_event_a")
print("done")
event.push("custom_event_b", 2)

输出:

custom_event_a
done
custom_event_b	2

目录