并发使程序在多个线程上运行,一个示例是Web服务器同时响应多个客户端,并发通过消息传递很容易,但是它们基于数据共享则很难编写。
启动线程
函数spawn()将指针作为参数,并从该函数启动新线程,该函数执行的任何操作,包括它可能调用的其他函数,都将在新线程上执行。
import std.stdio; import std.stdio; import std.concurrency; import core.thread;void worker(int a) { foreach (i; 0 .. 4) { Thread.sleep(1); writeln("Worker Thread ",a + i); } }
void main() { foreach (i; 1 .. 4) { Thread.sleep(2); writeln("Main Thread ",i); spawn(≈worker, i * 5); }
writeln("main is done.");
}
编译并执行上述代码后,它将读取上一部分中创建的文件,并产生以下输出-
Main Thread 1 Worker Thread 5 Main Thread 2 Worker Thread 6 Worker Thread 10 Main Thread 3 main is done. Worker Thread 7 Worker Thread 11 Worker Thread 15 Worker Thread 8 Worker Thread 12 Worker Thread 16 Worker Thread 13 Worker Thread 17 Worker Thread 18
线程标识符
在模块级别全局可用的 thisTid 变量始终是当前线程的ID,当调用spawn时,您也可以接收threadId。一个如下所示。
import std.stdio; import std.concurrency;void printTid(string tag) { writefln("%s: %s, address: %s", tag, thisTid, &thisTid); }
void worker() { printTid("Worker"); }
void main() { Tid myWorker=spawn(&worker);
printTid("Owner ");
writeln(myWorker); }
编译并执行上述代码后,它将读取上一部分中创建的文件,并产生以下输出-
Owner : Tid(std.concurrency.MessageBox), address: 10C71A59C Worker: Tid(std.concurrency.MessageBox), address: 10C71A59C Tid(std.concurrency.MessageBox)
消息传递
函数send()发送消息,而函数receiveOnly()等待特定类型的消息。还有其他名为prioritySend(),receive()和receiveTimeout()的函数,稍后将进行说明。
以下示例向其工作程序发送int类型的消息,并等待来自double类型的消息,线程继续来回发送消息,直到发送一个负整数。一个如下所示。
import std.stdio; import std.concurrency; import core.thread; import std.conv;void workerFunc(Tid tid) { int value=0;
while (value >= 0) { value=receiveOnly!int(); auto result=to!double(value) * 5; tid.send(result); } }void main() { Tid worker=spawn(&workerFunc,thisTid);
foreach (value; 5 .. 10) { worker.send(value); auto result=receiveOnly!double(); writefln("sent: %s, received: %s", value, result); }
worker.send(-1); }
编译并执行上述代码后,它将读取上一部分中创建的文件,并产生以下输出-
sent: 5, received: 25 sent: 6, received: 30 sent: 7, received: 35 sent: 8, received: 40 sent: 9, received: 45
等待传递消息
下面显示了一个带有等待消息传递的简单示例。
import std.stdio;
import std.concurrency;
import core.thread;
import std.conv;
void workerFunc(Tid tid) {
Thread.sleep(dur!("msecs")( 500 ),);
tid.send("hello");
}
void main() {
spawn(&workerFunc,thisTid);
writeln("Waiting for a message");
bool received=false;
while (!received) {
received=receiveTimeout(dur!("msecs")( 100 ), (string message) {
writeln("received: ", message);
});
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">received</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
writeln</span><span class="pun">(</span><span class="str">"... no message yet"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
}
}
编译并执行上述代码后,它将读取上一部分中创建的文件,并产生以下输出-
Waiting for a message ... no message yet ... no message yet ... no message yet ... no message yet received: hello