概要
色々な言語での非同期サンプル集。
収録言語
JavaScript、VB.NET、C#、C++、D、Java、Scala、
Go、Ruby、Python、Scheme(Gauche)、Clojure
Parallelなものは一切考えず、Thread、Future系に統一しています。
それ以外にも知らずに古い技術で書いているものもあるかも。
以下のようなチャートを並列Sleepさせて各言語で実行します。
非同期タイムチャート
Times[ms]|0 :1000 :2000 :3000
TaskName |---------:---------:---------:----
WaitA |>>>>>>>> : |1 : :
WaitB |> : |1 : :
WaitC |>>>>>>>>>>>>>>>|1 : :
WaitD | : >]>>>>>> |4
WaitE | : >|2 : |4
WaitF | : >]>>>>>>>>>>>>|4
WaitG | : >>>>>>|3 :
Ended | B A: CF : GD E
実行した出力は以下のようになります。
コンソール
Begin Async
A:START
B:START
C:START
B:100
A:800
C:1500
--- Wall1 ---
D:START
E:START
F:START
E:100
--- Wall2 ---
G:START
G:690
--- Wall3 ---
D:800
F:1500
--- Wall4 ---
End Async
START=>B=>A=>C=>E=>G=>D=>F
ただし、一部言語はタスク実行のオーバーヘッドからか、
DとGの終了タイミングが入れ替わることもあります。
これもまた非同期だからこそ。
JavaScript
setTimeout(ES3動作可)
function BasicAsync(){
var catchAsync="\nSTART";
var myAsync=function(name,wait,callback){
console.log(name+":START");
setTimeout(function(){
console.log(name+":"+wait);
catchAsync+="=>"+name;
callback();
},wait);
}
console.log("Begin Async");
var WaitAll=3;
myAsync("A",800,WaitABC);
myAsync("B",100,WaitABC);
myAsync("C",1500,WaitABC);
function WaitABC(){
WaitAll--;
if(WaitAll!=0)return;
console.log("--- Wall1 ---");
var WaitAny=1;
WaitAll=3;
myAsync("D",800,WaitDEF);
myAsync("E",100,WaitDEF);
myAsync("F",1500,WaitDEF);
function WaitDEF(){
WaitAny--;
WaitAll--;
if(WaitAny==0){
console.log("--- Wall2 ---");
myAsync("G",690,function(){
console.log("--- Wall3 ---");
});
}
else if(WaitAll==0){
console.log("--- Wall4 ---");
console.log("End Async");
console.log(catchAsync);
}
}
}
}
BasicAsync();
Promise<T>
"use strict";
function BasicAsync(){
var catchAsync="\nSTART";
const myAsync=(name,wait)=>new Promise(
function(resolve){
console.log(`${name}:START`);
setTimeout(resolve,wait);
}).then(()=>{
console.log(`${name}:${wait}`);
catchAsync+="=>"+name;
return Promise.resolve();
}
);
console.log("Begin Async");
const WaitA=myAsync("A",800);
const WaitB=myAsync("B",100);
const WaitC=myAsync("C",1500);
var WaitGroup;
Promise.all([WaitA,WaitB,WaitC])
.then(value=>{
console.log("--- Wall1 ---");
const WaitD=myAsync("D",800);
const WaitE=myAsync("E",100);
const WaitF=myAsync("F",1500);
WaitGroup=[WaitD,WaitE,WaitF];
return Promise.race(WaitGroup);
})
.then(value=>{
console.log("--- Wall2 ---");
return myAsync("G",690);
})
.then(value=>{
console.log("--- Wall3 ---");
return Promise.all(WaitGroup);
})
.then(value=>{
console.log("--- Wall4 ---");
console.log("End Async");
console.log(catchAsync);
});
}
BasicAsync();
Generator/Promise<T>
"use strict";
function BasicAsync(){
const g=(function*(){
var catchAsync="\nSTART";
const myAsync=(name,wait)=>new Promise(
function(resolve){
const g=(function*(){
console.log(`${name}:START`);
yield setTimeout(()=>g.next(),wait);
console.log(`${name}:${wait}`);
catchAsync+="=>"+name;
resolve();
})();
g.next();
}
);
console.log("Begin Async");
const WaitA=myAsync("A",800);
const WaitB=myAsync("B",100);
const WaitC=myAsync("C",1500);
yield Promise.all([WaitA,WaitB,WaitC]).then(()=>g.next());
console.log("--- Wall1 ---");
const WaitD=myAsync("D",800);
const WaitE=myAsync("E",100);
const WaitF=myAsync("F",1500);
const WaitGroup=[WaitD,WaitE,WaitF];
yield Promise.race(WaitGroup).then(()=>g.next());
console.log("--- Wall2 ---");
yield myAsync("G",690).then(()=>g.next());
console.log("--- Wall3 ---");
yield Promise.all(WaitGroup).then(()=>g.next());
console.log("--- Wall4 ---");
console.log("End Async");
console.log(catchAsync);
})();
g.next();
}
BasicAsync();
Async/Await(TypeScript & ES.Next)
async function BasicAsync(){
var catchAsync:string="\nSTART";
const myAsync:(string,number)=>Promise<void>=async (name,wait)=>{
console.log(`${name}:START`);
await new Promise(resolve=>setTimeout(resolve,wait));
console.log(`${name}:${wait}`);
catchAsync+="=>"+name;
};
console.log("Begin Async");
const WaitA:Promise<void>=myAsync("A",800);
const WaitB:Promise<void>=myAsync("B",100);
const WaitC:Promise<void>=myAsync("C",1500);
await Promise.all([WaitA,WaitB,WaitC]);
console.log("--- Wall1 ---");
const WaitD:Promise<void>=myAsync("D",800);
const WaitE:Promise<void>=myAsync("E",100);
const WaitF:Promise<void>=myAsync("F",1500);
const WaitGroup:Promise<void>[]=[WaitD,WaitE,WaitF];
await Promise.race(WaitGroup);
console.log("--- Wall2 ---");
await myAsync("G",690);
console.log("--- Wall3 ---");
await Promise.all(WaitGroup);
console.log("--- Wall4 ---");
console.log("End Async");
console.log(catchAsync);
}
BasicAsync();
Cluster(Node.js)
"use strict";
const cluster=require("cluster");
function BasicAsync(){
if(cluster.isWorker){
let name=process.argv[2];
let wait=parseInt(process.argv[3],10);
console.log(`${name}:START`);
setTimeout(()=>{
console.log(`${name}:${wait}`);
process.send(`=>${name}`);
cluster.worker.kill();
},wait);
return;
}
var catchAsync="\nSTART";
const nextAsync=function(worker,callback){
worker.once("message",name=>{
catchAsync+=name;
callback();
});
};
const myAsync=function(name,wait){
cluster.setupMaster({args:[name,wait]});
return cluster.fork();
}
console.log("Begin Async");
const WaitA=myAsync("A",800);
const WaitB=myAsync("B",100);
const WaitC=myAsync("C",1500);
var WaitGroup=[WaitA,WaitB,WaitC];
var WaitAll=WaitGroup.length;
WaitGroup.forEach(val=>nextAsync(val,WaitABC));
function WaitABC(){
WaitAll--;
if(WaitAll!=0)return;
console.log("--- Wall1 ---");
const WaitD=myAsync("D",800);
const WaitE=myAsync("E",100);
const WaitF=myAsync("F",1500);
WaitGroup=[WaitD,WaitE,WaitF];
var WaitAny=1;
WaitAll=WaitGroup.length;
WaitGroup.forEach(val=>nextAsync(val,WaitDEF));
function WaitDEF(){
WaitAny--;
WaitAll--;
if(WaitAny==0){
console.log("--- Wall2 ---");
nextAsync(myAsync("G",690),()=>{
console.log("--- Wall3 ---");
});
}
else if(WaitAll==0){
console.log("--- Wall4 ---");
console.log("End Async");
console.log(catchAsync);
}
}
}
}
BasicAsync();
Cluster/Generator/Promise(Node.js)
"use strict";
const cluster=require("cluster");
function BasicAsync(){
if(cluster.isWorker){
let name=process.argv[2];
let wait=parseInt(process.argv[3],10);
console.log(`${name}:START`);
new Promise(resolve=>setTimeout(resolve,wait)).then(()=>{
console.log(`${name}:${wait}`);
process.send(`=>${name}`);
cluster.worker.kill();
});
return;
}
const g=(function*(){
var catchAsync="\nSTART";
const myAsync=(name,wait)=>new Promise(resolve=>{
cluster.setupMaster({args:[name,wait]});
cluster.fork().once("message",name=>{
catchAsync+=name;
resolve();
});
});
console.log("Begin Async");
const WaitA=myAsync("A",800);
const WaitB=myAsync("B",100);
const WaitC=myAsync("C",1500);
yield Promise.all([WaitA,WaitB,WaitC]).then(()=>g.next());
console.log("--- Wall1 ---");
const WaitD=myAsync("D",800);
const WaitE=myAsync("E",100);
const WaitF=myAsync("F",1500);
const WaitGroup=[WaitD,WaitE,WaitF];
yield Promise.race(WaitGroup).then(()=>g.next());
console.log("--- Wall2 ---");
yield myAsync("G",690).then(()=>g.next());
console.log("--- Wall3 ---");
yield Promise.all(WaitGroup).then(()=>g.next());
console.log("--- Wall4 ---");
console.log("End Async");
console.log(catchAsync);
})();
g.next();
}
BasicAsync();
Web Worker/Generator/Promise(html5)
<html>
<head>
<title>Web Worker Console</title>
<style>
body{
font-family:monospace;
background-color:#000;
color:#CCC;
}
</style>
</head>
<body>
<script>
const println=function(txt){
document.body.innerText+=txt+"\n";
};
function BasicAsync(){
const myAsyncFunc=window.URL.createObjectURL(new Blob([`
onmessage=function(event){
const d=event.data;
setTimeout(
()=>postMessage({
addCatch:\`=>\${d.name}\`
}),d.wait
);
};
`],{type:"text/javascript"}));
const g=(function*(){
var catchAsync="\nSTART";
const myAsync=(name,wait)=>new Promise(resolve=>{
const t=new Worker(myAsyncFunc);
println(`${name}:START`);
t.postMessage({
name:name,
wait:wait
});
t.onmessage=event=>{
catchAsync+=event.data.addCatch;
println(`${name}:${wait}`);
resolve();
};
});
println("Begin Async");
const WaitA=myAsync("A",800);
const WaitB=myAsync("B",100);
const WaitC=myAsync("C",1500);
yield Promise.all([WaitA,WaitB,WaitC]).then(()=>g.next());
println("--- Wall1 ---");
const WaitD=myAsync("D",800);
const WaitE=myAsync("E",100);
const WaitF=myAsync("F",1500);
const WaitGroup=[WaitD,WaitE,WaitF];
yield Promise.race(WaitGroup).then(()=>g.next());
println("--- Wall2 ---");
yield myAsync("G",690).then(()=>g.next());
println("--- Wall3 ---");
yield Promise.all(WaitGroup).then(()=>g.next());
println("--- Wall4 ---");
println("End Async");
println(catchAsync);
})();
g.next();
}
addEventListener("load",function(){
BasicAsync()
});
</script>
</body>
</html>
VB.NET
Thread(.Net2.0動作可)
Imports System
Imports System.Console
Imports System.Threading
Module Program
Dim catchAsync As String=vbLf & "START"
Sub myAsyncFunc(params As Object)
Dim name As String=params(0)
Dim wait As Integer=params(1)
WriteLine(name & ":START")
Thread.Sleep(wait)
WriteLine(name & ":" & wait)
catchAsync &= "=>" & name
End Sub
Function myAsync(name As String,wait As Integer) As Thread
Dim t As New Thread(AddressOf myAsyncFunc)
t.Start(New Object(){name,wait})
Return t
End Function
Sub BasicAsync()
WriteLine("Begin Async")
Dim WaitA As Thread=myAsync("A",800)
Dim WaitB As Thread=myAsync("B",100)
Dim WaitC As Thread=myAsync("C",1500)
For Each val As Thread In New Thread(){WaitA,WaitB,WaitC}
val.Join()
Next
WriteLine("--- Wall1 ---")
Dim WaitD As Thread=myAsync("D",800)
Dim WaitE As Thread=myAsync("E",100)
Dim WaitF As Thread=myAsync("F",1500)
Dim WaitGroup As Thread()={WaitD,WaitE,WaitF}
Do:For Each val As Thread In WaitGroup
If Not val.IsAlive Then Exit Do
Next:Loop
WriteLine("--- Wall2 ---")
myAsync("G",690).Join()
WriteLine("--- Wall3 ---")
For Each val As Thread In WaitGroup
val.Join()
Next
WriteLine("--- Wall4 ---")
WriteLine("End Async")
WriteLine(catchAsync)
End Sub
Sub Main()
BasicAsync()
End Sub
End Module
IAsyncResult/BeginInvoke/EndInvoke/WaitHandle
Option Strict On
Imports System
Imports System.Console
Imports System.Threading
Imports System.Windows.Forms
Module Program
Sub BasicAsync()
Dim workMin As Integer
Dim ioMin As Integer
ThreadPool.GetMinThreads(workMin,ioMin)
ThreadPool.SetMinThreads(1000,ioMin)
Dim t As New Thread(Sub()
Dim catchAsync As String=$"{vbLf}START"
Dim myAsyncFunc As Action(Of String,Integer)=Sub(name,wait)
WriteLine($"{name}:START")
Thread.Sleep(wait)
WriteLine($"{name}:{wait}")
catchAsync &= "=>" & name
End Sub
Dim myAsync As Func(Of String,Integer,IAsyncResult)=
Function(name,wait)myAsyncFunc.BeginInvoke(name,wait,Nothing,Nothing)
Dim waitAsync As Action(Of IAsyncResult)=
Sub(val)myAsyncFunc.EndInvoke(val)
WriteLine("Begin Async")
Dim WaitA As IAsyncResult=myAsync("A",800)
Dim WaitB As IAsyncResult=myAsync("B",100)
Dim WaitC As IAsyncResult=myAsync("C",1500)
WaitHandle.WaitAll(Array.ConvertAll({WaitA,WaitB,WaitC},Function(val)val.AsyncWaitHandle))
WriteLine("--- Wall1 ---")
Dim WaitD As IAsyncResult=myAsync("D",800)
Dim WaitE As IAsyncResult=myAsync("E",100)
Dim WaitF As IAsyncResult=myAsync("F",1500)
Dim WaitGroup As WaitHandle()=Array.ConvertAll({WaitD,WaitE,WaitF},Function(val)val.AsyncWaitHandle)
WaitHandle.WaitAny(WaitGroup)
WriteLine("--- Wall2 ---")
waitAsync(myAsync("G",690))
WriteLine("--- Wall3 ---")
WaitHandle.WaitAll(WaitGroup)
WriteLine("--- Wall4 ---")
WriteLine("End Async")
WriteLine(catchAsync)
End Sub)
t.Start()
t.Join()
End Sub
Sub Main()
BasicAsync()
End Sub
End Module
Task(Of T)
Option Strict On
Imports System
Imports System.Console
Imports System.Threading
Imports System.Threading.Tasks
Module Program
Sub BasicAsync()
Dim workMin As Integer
Dim ioMin As Integer
ThreadPool.GetMinThreads(workMin,ioMin)
ThreadPool.SetMinThreads(1000,ioMin)
Dim catchAsync As String=$"{vbLf}START"
Dim myAsync As Func(Of String,Integer,Task)=Function(name,wait) Task.Run(
Sub()
WriteLine($"{name}:START")
Thread.Sleep(wait)
WriteLine($"{name}:{wait}")
catchAsync &= "=>" & name
End Sub
)
WriteLine("Begin Async")
Dim WaitA As Task=myAsync("A",800)
Dim WaitB As Task=myAsync("B",100)
Dim WaitC As Task=myAsync("C",1500)
Task.WaitAll(WaitA,WaitB,WaitC)
WriteLine("--- Wall1 ---")
Dim WaitD As Task=myAsync("D",800)
Dim WaitE As Task=myAsync("E",100)
Dim WaitF As Task=myAsync("F",1500)
Dim WaitGroup As Task()={WaitD,WaitE,WaitF}
Task.WaitAny(WaitGroup)
WriteLine("--- Wall2 ---")
myAsync("G",690).Wait()
WriteLine("--- Wall3 ---")
Task.WaitAll(WaitGroup)
WriteLine("--- Wall4 ---")
WriteLine("End Async")
WriteLine(catchAsync)
End Sub
Sub Main()
BasicAsync()
End Sub
End Module
Async/Await
Option Strict On
Imports System
Imports System.Console
Imports System.Threading
Imports System.Threading.Tasks
Module Program
Async Function BasicAsync() As Task
Dim workMin As Integer
Dim ioMin As Integer
ThreadPool.GetMinThreads(workMin,ioMin)
ThreadPool.SetMinThreads(1000,ioMin)
Dim catchAsync As String=$"{vbLf}START"
Dim myAsync As Func(Of String,Integer,Task)=Async Function(name,wait)
WriteLine($"{name}:START")
Await Task.Delay(wait)
WriteLine($"{name}:{wait}")
catchAsync &= "=>" & name
End Function
WriteLine("Begin Async")
Dim WaitA As Task=myAsync("A",800)
Dim WaitB As Task=myAsync("B",100)
Dim WaitC As Task=myAsync("C",1500)
Await Task.WhenAll(WaitA,WaitB,WaitC)
WriteLine("--- Wall1 ---")
Dim WaitD As Task=myAsync("D",800)
Dim WaitE As Task=myAsync("E",100)
Dim WaitF As Task=myAsync("F",1500)
Dim WaitGroup As Task()={WaitD,WaitE,WaitF}
Await Task.WhenAny(WaitGroup)
WriteLine("--- Wall2 ---")
Await myAsync("G",690)
WriteLine("--- Wall3 ---")
Await Task.WhenAll(WaitGroup)
WriteLine("--- Wall4 ---")
WriteLine("End Async")
WriteLine(catchAsync)
End Function
Sub Main()
BasicAsync().Wait()
End Sub
End Module
C#
IAsyncResult/BeginInvoke/EndInvoke/WaitHandle
using System;
using System.Threading;
using System.Windows.Forms;
class Program{
static void BasicAsync(){
int workMin;
int ioMin;
ThreadPool.GetMinThreads(out workMin,out ioMin);
ThreadPool.SetMinThreads(1000,ioMin);
string catchAsync="\nSTART";
Action<string,int> myAsyncFunc=(name,wait)=>{
Console.WriteLine($"{name}:START");
Thread.Sleep(wait);
Console.WriteLine($"{name}:{wait}");
catchAsync+="=>"+name;
};
Func<string,int,IAsyncResult> myAsync=
(name,wait)=>myAsyncFunc.BeginInvoke(name,wait,null,null);
Action<IAsyncResult> waitAsync=
val=>myAsyncFunc.EndInvoke(val);
Console.WriteLine("Begin Async");
IAsyncResult WaitA=myAsync("A",800);
IAsyncResult WaitB=myAsync("B",100);
IAsyncResult WaitC=myAsync("C",1500);
WaitHandle.WaitAll(Array.ConvertAll(new IAsyncResult[]{WaitA,WaitB,WaitC},val=>val.AsyncWaitHandle));
Console.WriteLine("--- Wall1 ---");
IAsyncResult WaitD=myAsync("D",800);
IAsyncResult WaitE=myAsync("E",100);
IAsyncResult WaitF=myAsync("F",1500);
WaitHandle[] WaitGroup=Array.ConvertAll(new IAsyncResult[]{WaitD,WaitE,WaitF},val=>val.AsyncWaitHandle);
WaitHandle.WaitAny(WaitGroup);
Console.WriteLine("--- Wall2 ---");
waitAsync(myAsync("G",690));
Console.WriteLine("--- Wall3 ---");
WaitHandle.WaitAll(WaitGroup);
Console.WriteLine("--- Wall4 ---");
Console.WriteLine("End Async");
Console.WriteLine(catchAsync);
}
static void Main(){
BasicAsync();
}
}
Task<T>
using System;
using System.Threading;
using System.Threading.Tasks;
class Program{
static void BasicAsync(){
int workMin;
int ioMin;
ThreadPool.GetMinThreads(out workMin,out ioMin);
ThreadPool.SetMinThreads(1000,ioMin);
string catchAsync="\nSTART";
Func<string,int,Task> myAsync=(name,wait)=>Task.Run(
delegate(){
Console.WriteLine($"{name}:START");
Thread.Sleep(wait);
Console.WriteLine($"{name}:{wait}");
catchAsync+="=>"+name;
}
);
Console.WriteLine("Begin Async");
Task WaitA=myAsync("A",800);
Task WaitB=myAsync("B",100);
Task WaitC=myAsync("C",1500);
Task.WaitAll(WaitA,WaitB,WaitC);
Console.WriteLine("--- Wall1 ---");
Task WaitD=myAsync("D",800);
Task WaitE=myAsync("E",100);
Task WaitF=myAsync("F",1500);
Task[] WaitGroup={WaitD,WaitE,WaitF};
Task.WaitAny(WaitGroup);
Console.WriteLine("--- Wall2 ---");
myAsync("G",690).Wait();
Console.WriteLine("--- Wall3 ---");
Task.WaitAll(WaitGroup);
Console.WriteLine("--- Wall4 ---");
Console.WriteLine("End Async");
Console.WriteLine(catchAsync);
}
static void Main(){
BasicAsync();
}
}
Async/Await
using System;
using System.Threading;
using System.Threading.Tasks;
class Program{
static async Task BasicAsync(){
int workMin;
int ioMin;
ThreadPool.GetMinThreads(out workMin,out ioMin);
ThreadPool.SetMinThreads(1000,ioMin);
string catchAsync="\nSTART";
Func<string,int,Task> myAsync=async (name,wait)=>{
Console.WriteLine($"{name}:START");
await Task.Delay(wait);
Console.WriteLine($"{name}:{wait}");
catchAsync+="=>"+name;
};
Console.WriteLine("Begin Async");
Task WaitA=myAsync("A",800);
Task WaitB=myAsync("B",100);
Task WaitC=myAsync("C",1500);
await Task.WhenAll(WaitA,WaitB,WaitC);
Console.WriteLine("--- Wall1 ---");
Task WaitD=myAsync("D",800);
Task WaitE=myAsync("E",100);
Task WaitF=myAsync("F",1500);
Task[] WaitGroup={WaitD,WaitE,WaitF};
await Task.WhenAny(WaitGroup);
Console.WriteLine("--- Wall2 ---");
await myAsync("G",690);
Console.WriteLine("--- Wall3 ---");
await Task.WhenAll(WaitGroup);
Console.WriteLine("--- Wall4 ---");
Console.WriteLine("End Async");
Console.WriteLine(catchAsync);
}
static void Main(){
BasicAsync().Wait();
}
}
C++
future<T>/async(C++11)
#include <iostream>
#include <string>
#include <functional>
#include <thread>
#include <future>
using namespace std;
void BasicAsync(){
string catchAsync="\nSTART";
function<future<void>(string,int)> myAsync=[&](auto name,auto wait){
return async(launch::async,
[&catchAsync,name,wait]{
cout<<name<<":START\n"<<flush;
this_thread::sleep_for(chrono::milliseconds(wait));
cout<<name<<":"<<wait<<"\n"<<flush;
catchAsync+="=>"+name;
}
);
};
cout<<"Begin Async"<<endl;
future<void> WaitA=myAsync("A",800);
future<void> WaitB=myAsync("B",100);
future<void> WaitC=myAsync("C",1500);
for(auto t:{&WaitA,&WaitB,&WaitC})t->wait();
cout<<"--- Wall1 ---"<<endl;
future<void> WaitD=myAsync("D",800);
future<void> WaitE=myAsync("E",100);
future<void> WaitF=myAsync("F",1500);
future<void>* WaitGroup[]={&WaitD,&WaitE,&WaitF};
for(;;){
for(auto t:WaitGroup){
if(t->wait_for(chrono::seconds(0))==future_status::ready){
goto WaitAny;
}
}
}
WaitAny:
cout<<"--- Wall2 ---"<<endl;
myAsync("G",690).wait();
cout<<"--- Wall3 ---"<<endl;
for(auto t:WaitGroup)t->wait();
cout<<"--- Wall4 ---"<<endl;
cout<<"End Async"<<endl;
cout<<catchAsync<<endl;
}
int main(){
BasicAsync();
}
D言語
core.thread.Thread/ThreadGroup
import std.stdio;
import std.conv;
import core.thread;
void BasicAsync(){
string catchAsync="\nSTART";
Thread delegate(string,int) myAsync=delegate(name,wait){
auto t=new Thread(
delegate(){
writef("%s:START\n",name);
Thread.sleep(dur!"msecs"(wait));
writef("%s:%d\n",name,wait);
catchAsync~="=>"~name;
}
);
t.start;
return t;
};
writeln("Begin Async");
Thread WaitA=myAsync("A",800);
Thread WaitB=myAsync("B",100);
Thread WaitC=myAsync("C",1500);
auto WaitGroup=new ThreadGroup();
foreach(t;[WaitA,WaitB,WaitC])WaitGroup.add(t);
WaitGroup.joinAll();
writeln("--- Wall1 ---");
Thread WaitD=myAsync("D",800);
Thread WaitE=myAsync("E",100);
Thread WaitF=myAsync("F",1500);
WaitGroup=new ThreadGroup();
foreach(t;[WaitD,WaitE,WaitF])WaitGroup.add(t);
WaitAny:for(;;){
foreach(t;WaitGroup)if(!t.isRunning)break WaitAny;
}
writeln("--- Wall2 ---");
Thread WaitG=myAsync("G",690);
WaitG.join();
writeln("--- Wall3 ---");
WaitGroup.joinAll();
writeln("--- Wall4 ---");
writeln("End Async");
writeln(catchAsync);
}
void main(){
BasicAsync();
}
Java
Future<T>
import java.util.List;
import java.util.Arrays;
import java.util.function.*;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ExecutionException;
class Program{
static void BasicAsync(){
ExecutorService TP=new ForkJoinPool(1000);
String[] catchAsync={"\nSTART"};
BiFunction<String,Integer,Future<Void>> myAsync=(name,wait)->TP.submit(
()->{
System.out.printf("%s:START\n",name);
Thread.sleep(wait);
System.out.printf("%s:%d\n",name,wait);
catchAsync[0]+="=>"+name;
return null;
}
);
try {
System.out.println("Begin Async");
Future<Void> WaitA=myAsync.apply("A",800);
Future<Void> WaitB=myAsync.apply("B",100);
Future<Void> WaitC=myAsync.apply("C",1500);
for(Future<Void> t:Arrays.asList(WaitA,WaitB,WaitC))t.get();
System.out.println("--- Waii1 ---");
Future<Void> WaitD=myAsync.apply("D",800);
Future<Void> WaitE=myAsync.apply("E",100);
Future<Void> WaitF=myAsync.apply("F",1500);
List<Future<Void>> WaitGroup=Arrays.asList(WaitD,WaitE,WaitF);
WaitAny:for(;;){
for(Future<Void> t:WaitGroup)if(t.isDone())break WaitAny;
}
System.out.println("--- Waii2 ---");
myAsync.apply("G",690).get();
System.out.println("--- Waii3 ---");
for(Future<Void> t:WaitGroup)t.get();
System.out.println("--- Waii4 ---");
System.out.println("End Async");
System.out.println(catchAsync[0]);
}
catch (InterruptedException | ExecutionException e){}
}
public static void main(String args[]){
BasicAsync();
}
}
CompletableFuture<T>
import java.util.List;
import java.util.Arrays;
import java.util.function.*;
import java.util.concurrent.CompletableFuture;
class Program{
static void BasicAsync(){
String[] catchAsync={"\nSTART"};
BiFunction<String,Integer,CompletableFuture<Void>> myAsync=(name,wait)->CompletableFuture.runAsync(
()->{
System.out.printf("%s:START\n",name);
try{
Thread.sleep(wait);
}
catch(Exception e){}
System.out.printf("%s:%d\n",name,wait);
catchAsync[0]+="=>"+name;
}
);
System.out.println("Begin Async");
CompletableFuture<Void> WaitA=myAsync.apply("A",800);
CompletableFuture<Void> WaitB=myAsync.apply("B",100);
CompletableFuture<Void> WaitC=myAsync.apply("C",1500);
CompletableFuture.allOf(WaitA,WaitB,WaitC).join();
System.out.println("--- Waii1 ---");
CompletableFuture<Void> WaitD=myAsync.apply("D",800);
CompletableFuture<Void> WaitE=myAsync.apply("E",100);
CompletableFuture<Void> WaitF=myAsync.apply("F",1500);
List<CompletableFuture<Void>> WaitGroup=Arrays.asList(WaitD,WaitE,WaitF);
CompletableFuture.anyOf(WaitGroup.toArray(new CompletableFuture[WaitGroup.size()])).join();
System.out.println("--- Waii2 ---");
myAsync.apply("G",690).join();
System.out.println("--- Waii3 ---");
CompletableFuture.allOf(WaitGroup.toArray(new CompletableFuture[WaitGroup.size()])).join();
System.out.println("--- Waii4 ---");
System.out.println("End Async");
System.out.println(catchAsync[0]);
}
public static void main(String args[]){
BasicAsync();
}
}
Scala
Futule[T]/Promise[T]
import scala.concurrent._
import scala.concurrent.duration.Duration
import java.util.concurrent.ForkJoinPool
implicit val TP=ExecutionContext.fromExecutorService(new ForkJoinPool(1000))
def BasicAsync(){
var catchAsync="\nSTART"
val myAsync:(String,Int)=>Future[Unit]=(name,wait)=>Future{
printf("%s:START\n",name)
Thread.sleep(wait)
printf("%s:%d\n",name,wait)
catchAsync+="=>"+name
}
println("Begin Async")
val WaitA:Future[Unit]=myAsync("A",800)
val WaitB:Future[Unit]=myAsync("B",100)
val WaitC:Future[Unit]=myAsync("C",1500)
for(t<-List(WaitA,WaitB,WaitC))Await.ready(t,Duration.Inf)
println("--- Wall1 ---")
val WaitD:Future[Unit]=myAsync("D",800)
val WaitE:Future[Unit]=myAsync("E",100)
val WaitF:Future[Unit]=myAsync("F",1500)
val WaitGroup:List[Future[Unit]]=List(WaitD,WaitE,WaitF)
val WaitAny=Promise[Unit]
for(t<-WaitGroup)t.foreach(Unit=>WaitAny.trySuccess(Unit))
Await.ready(WaitAny.future,Duration.Inf)
println("--- Wall2 ---")
Await.ready(myAsync("G",690),Duration.Inf)
println("--- Wall3 ---")
for(t<-WaitGroup)Await.ready(t,Duration.Inf)
println("--- Wall4 ---")
println("End Async")
println(catchAsync)
}
BasicAsync()
Go言語
Goroutine/Channel
package main
import(
"fmt"
"time"
)
func BasicAsync(){
catchAsync:="\nSTART"
myAsync:=func(name string,wait int) chan struct{}{
ch:=make(chan struct{})
go func(){
fmt.Printf("%s:START\n",name)
time.Sleep(time.Duration(wait)*time.Millisecond)
fmt.Printf("%s:%d\n",name,wait)
catchAsync+="=>"+name
defer close(ch)
}()
return ch
}
fmt.Println("Begin Async")
WaitA:=myAsync("A",800)
WaitB:=myAsync("B",100)
WaitC:=myAsync("C",1500)
for _,ch:=range []chan struct{}{WaitA,WaitB,WaitC} {
<-ch
}
fmt.Println("--- Wall1 ---")
WaitD:=myAsync("D",800)
WaitE:=myAsync("E",100)
WaitF:=myAsync("F",1500)
WaitGroup:=[]chan struct{}{WaitD,WaitE,WaitF}
func(){
for ;; {
for _,ch:=range WaitGroup {
select {
case <-ch:
return
default:
}
}
}
}()
fmt.Println("--- Wall2 ---")
<-myAsync("G",690)
fmt.Println("--- Wall3 ---")
for _,ch:=range WaitGroup {
<-ch
}
fmt.Println("--- Wall4 ---")
fmt.Println("End Async")
fmt.Println(catchAsync)
}
func main(){
BasicAsync()
}
Goroutine/sync.WaitGroup
package main
import(
"fmt"
"time"
"sync"
)
func BasicAsync(){
catchAsync:="\nSTART"
myAsync:=func(name string,wait int,WG *sync.WaitGroup){
fmt.Printf("%s:START\n",name)
time.Sleep(time.Duration(wait)*time.Millisecond)
fmt.Printf("%s:%d\n",name,wait)
catchAsync+="=>"+name
defer WG.Done()
}
fmt.Println("Begin Async")
var WaitGroup sync.WaitGroup
WaitGroup.Add(3)
go myAsync("A",800,&WaitGroup)
go myAsync("B",100,&WaitGroup)
go myAsync("C",1500,&WaitGroup)
WaitGroup.Wait()
fmt.Println("--- Wall1 ---")
WaitGroup.Add(1)
go myAsync("D",800,&WaitGroup)
go myAsync("E",100,&WaitGroup)
go myAsync("F",1500,&WaitGroup)
WaitGroup.Wait()
fmt.Println("--- Wall2 ---")
var WaitG sync.WaitGroup
WaitG.Add(1)
go myAsync("G",690,&WaitG)
WaitG.Wait()
fmt.Println("--- Wall3 ---")
WaitGroup.Add(3-1)
WaitGroup.Wait()
fmt.Println("--- Wall4 ---")
fmt.Println("End Async")
fmt.Println(catchAsync)
}
func main(){
BasicAsync()
}
Ruby
Thread/ThreadsWait
require "thwait"
def basicAsync()
catchAsync="\nSTART"
myAsync=lambda do |name,wait|
return Thread.new(name,wait) do |name,wait|
puts "#{name}:START"
sleep (wait.to_f/1000)
puts "#{name}:#{wait}"
catchAsync << "=>#{name}"
end
end
puts "BeginAsync"
waitA=myAsync["A",800]
waitB=myAsync["B",100]
waitC=myAsync["C",1500]
ThreadsWait.all_waits(waitA,waitB,waitC)
puts "--- Wall1 ---"
waitD=myAsync["D",800]
waitE=myAsync["E",100]
waitF=myAsync["F",1500]
waitGroup=ThreadsWait.new(waitD,waitE,waitF)
waitGroup.next_wait
puts "--- Wall2 ---"
myAsync["G",690].join
puts "--- Wall3 ---"
waitGroup.all_waits
puts "--- Wall4 ---"
puts "End Async"
puts catchAsync
end
basicAsync
Python
Thread
import time
import threading
catchAsync="\nSTART"
def BasicAsync():
def myAsync(name,wait):
def myAsync(name,wait):
global catchAsync
print("{0}:START".format(name))
time.sleep(wait/1000)
print("{0}:{1}".format(name,wait))
catchAsync+="=>"+name
t=threading.Thread(target=myAsync,args=(name,wait,))
t.start()
return t
print("Begin Async")
WaitA=myAsync("A",800)
WaitB=myAsync("B",100)
WaitC=myAsync("C",1500)
for t in [WaitA,WaitB,WaitC]:
t.join()
print("--- Wall1 ---")
WaitD=myAsync("D",800)
WaitE=myAsync("E",100)
WaitF=myAsync("F",1500)
WaitGroup=[WaitD,WaitE,WaitF]
def WaitAny():
while True:
for t in WaitGroup:
if not t.isAlive():
return
WaitAny()
print("--- Wall2 ---")
myAsync("G",690).join()
print("--- Wall3 ---")
for t in WaitGroup:
t.join()
print("--- Wall4 ---")
print("End Async")
print(catchAsync)
BasicAsync()
concurrent.futures/ProcessPoolExecutor
import time
import concurrent.futures
futures=concurrent.futures
def myAsyncFunc(name,wait):
print("{0}:START".format(name))
time.sleep(wait/1000)
print("{0}:{1}".format(name,wait))
return "=>"+name
def BasicAsync():
catchAsync="\nSTART"
if __name__=="__main__":
with futures.ProcessPoolExecutor() as TP:
def myAsync(name,wait):
return TP.submit(myAsyncFunc,name,wait)
print("Begin Async")
WaitA=myAsync("A",800)
WaitB=myAsync("B",100)
WaitC=myAsync("C",1500)
for val in futures.as_completed([WaitA,WaitB,WaitC]):
catchAsync+=val.result()
print("--- Wall1 ---")
WaitD=myAsync("D",800)
WaitE=myAsync("E",100)
WaitF=myAsync("F",1500)
WaitGroup=futures.wait([WaitD,WaitE,WaitF],
return_when=futures.FIRST_COMPLETED)
for val in WaitGroup[0]:
catchAsync+=val.result()
print("--- Wall2 ---")
catchAsync+=myAsync("G",690).result()
print("--- Wall3 ---")
for val in futures.as_completed(WaitGroup[1]):
catchAsync+=val.result()
print("--- Wall4 ---")
print("End Async")
print(catchAsync)
BasicAsync()
concurrent.futures/ThreadPoolExecutor
import time
import concurrent.futures
futures=concurrent.futures
catchAsync="\nSTART"
def BasicAsync():
with futures.ThreadPoolExecutor(max_workers=1000) as TP:
def myAsync(name,wait):
def myAsync(name,wait):
global catchAsync
print("{0}:START".format(name))
time.sleep(wait/1000)
print("{0}:{1}".format(name,wait))
catchAsync+="=>"+name
return TP.submit(myAsync,name,wait)
print("Begin Async")
WaitA=myAsync("A",800)
WaitB=myAsync("B",100)
WaitC=myAsync("C",1500)
futures.wait([WaitA,WaitB,WaitC])
print("--- Wall1 ---")
WaitD=myAsync("D",800)
WaitE=myAsync("E",100)
WaitF=myAsync("F",1500)
WaitGroup=[WaitD,WaitE,WaitF]
futures.wait(WaitGroup,return_when=futures.FIRST_COMPLETED)
print("--- Wall2 ---")
myAsync("G",690).result()
print("--- Wall3 ---")
futures.wait(WaitGroup)
print("--- Wall4 ---")
print("End Async")
print(catchAsync)
BasicAsync()
asyncio/Async/Await(Python3.5)
import asyncio
catchAsync="\nSTART"
async def BasicAsync():
def myAsync(name,wait):
async def myAsync():
global catchAsync
print("{0}:START".format(name))
await asyncio.sleep(wait/1000)
print("{0}:{1}".format(name,wait))
catchAsync+="=>"+name
return asyncio.ensure_future(myAsync())
print("Begin Async")
WaitA=myAsync("A",800)
WaitB=myAsync("B",100)
WaitC=myAsync("C",1500)
await asyncio.wait([WaitA,WaitB,WaitC])
print("--- Wall1 ---")
WaitD=myAsync("D",800)
WaitE=myAsync("E",100)
WaitF=myAsync("F",1500)
WaitGroup=[WaitD,WaitE,WaitF]
await asyncio.wait(WaitGroup,return_when=asyncio.FIRST_COMPLETED)
print("--- Wall2 ---")
await myAsync("G",690)
print("--- Wall3 ---")
await asyncio.wait(WaitGroup)
print("--- Wall4 ---")
print("End Async")
print(catchAsync)
loop=asyncio.get_event_loop()
loop.run_until_complete(BasicAsync())
Scheme
gauche.thread(Gauche)
(use gauche.threads)
(define(BasicAsync)
(let(
(catchAsync "~%START")
)(let(
(myAsync (lambda(name wait)
(thread-start!
(make-thread
(lambda()
(format #t "~A:START~%" name)
(thread-sleep! (/ wait 1000))
(format #t "~A:~d~%" name wait)
(set! catchAsync (string-append catchAsync "=>" name))
)
)
)
))
(WaitAny '())
(WaitGroup '())
)
(format #t "Begin Async~%")
(set! WaitGroup `(
,(myAsync "A" 800)
,(myAsync "B" 100)
,(myAsync "C" 1500)
))
(dolist (th WaitGroup) (thread-join! th))
(format #t "--- Wall1 ---~%")
(set! WaitGroup `(
,(myAsync "D" 800)
,(myAsync "E" 100)
,(myAsync "F" 1500)
))
(set! WaitAny (lambda()
(call/cc
(lambda(cc)
(dolist (th WaitGroup)
(if (eq? (thread-state th) 'terminated)
(cc)
)
)
(WaitAny)
)
)
))
(WaitAny)
(format #t "--- Wall2 ---~%")
(thread-join! (myAsync "G" 690))
(format #t "--- Wall3 ---~%")
(dolist (th WaitGroup) (thread-join! th))
(format #t "--- Wall4 ---~%")
(format #t "End Async~%")
(format #t (format #f "~A~%" catchAsync))
))
)
(BasicAsync)
Clojure
future/promise(CLR)
(def catchAsync (atom ""))
(defn BasicAsync[]
(reset! catchAsync "\nSTART")
(let [
myAsync (fn[name,wait]
(future
(printf "%s:START\n" name)
(System.Threading.Thread/Sleep wait)
(printf "%s:%d\n" name wait)
(reset! catchAsync (str @catchAsync "=>" name))
)
)
]
(println "Begin Async")
(let [
WaitA (myAsync "A" 800)
WaitB (myAsync "B" 100)
WaitC (myAsync "C" 1500)
]
(doseq [t,[WaitA,WaitB,WaitC]](deref t))
(println "--- Wall1 ---")
(let [
WaitD (myAsync "D" 800)
WaitE (myAsync "E" 100)
WaitF (myAsync "F" 1500)
WaitGroup [WaitD,WaitE,WaitF]
]
(def WaitAny (promise))
(pmap (fn[t] (deliver WaitAny @t)) WaitGroup)
(deref WaitAny)
(println "--- Wall2 ---")
(deref (myAsync "G" 690))
(println "--- Wall3 ---")
(doseq [t,WaitGroup](deref t))
(println "--- Wall4 ---")
(println "End Async")
(println @catchAsync)
(shutdown-agents)
)
)
)
)
(BasicAsync)
非同期構文比較表
言語 | 非同期オブジェクト | 非同期オブジェクト生成&実行 | 非同期関数 | 非同期継続 | 非同期待機 | 返り値取得 | 待ち合わせ[All] | 待ち合わせ[Any] | 終了確認 |
---|---|---|---|---|---|---|---|---|---|
JavaScript | Promise | new Promise(...) | ― | t.then(R=>...) | ― | ― | Promise.all([t1,t2,t3]) | Promise.race([t1,t2,t3]) | ― |
Promise (Generator) | ― | function*() | ― | yield t.then(()=>[Generator].next()) | yield t.then(R=>[Generator].next(R)) | yield Promise.all([t1,t2,t3]).then(R=>[Generator].next(R)) | yield Promise.race([t1,t2,t3]).then(R=>[Generator].next(R)) | ― | |
Cluster.Worker(Node.js) | cluster.setupMaster([Options]) cluster.fork() |
― | t.on([event],R=>...) | ― | ― | ― | ― | t.isDead() | |
Web Worker(html5) | t=new Worker([URL]) t.postMessage([args]) |
― | t.onmessage=R=>... | ― | ― | ― | ― | ― | |
TypeScript | Promise (Async/Await) | ― | async function() | ― | await t | await t | await Promise.all([t1,t2,t3]) | await Promise.race([t1,t2,t3]) | ― |
VisualBasic | System.Threading.Thread | t=New Thread(...) t.start() |
― | ― | t.Join() | ― | ― | ― | t.IsAlive |
System.Windows.Forms.IAsyncResult | [Delegate].BeginInvoke([args ,]Nothing,Nothing) | ― | ― | [Delegate].EndInvoke(t) | [Delegate].EndInvoke(t) | WaitHandle.WaitAll({t1.AsyncWaitHandle,t2.AsyncWaitHandle}) | WaitHandle.WaitAny({t1.AsyncWaitHandle,t2.AsyncWaitHandle}) | t.IsCompleted | |
System.Threading.Tasks.Task | Task.Run(...) | ― | t.CountinueWith(Function(R)) | t.Wait() | t.Result | WaitAll(t1,t2,t3) | WaitAny(t1,t2,t3) | t.IsCompleted | |
WaitAll({t1,t2,t3}) | WaitAny({t1,t2,t3}) | ||||||||
WhenAll(t1,t2,t3).Wait() | WhenAny(t1,t2,t3).Wait() | ||||||||
WhenAll({t1,t2,t3}).Wait() | WhenAny({t1,t2,t3}).Wait() | ||||||||
Task (Async/Await) | ― | Async Function() | ― | Await t | Await t | Await WhenAll(t1,t2,t3) | Await WhenAny(t1,t2,t3) | ― | |
C# | System.Threading.Thread | t=new Thread(...) t.start() |
― | ― | t.Join() | ― | ― | ― | t.IsAlive |
System.Windows.Forms.IAsyncResult | [Delegate].BeginInvoke([args ,]Nothing,Nothing) | ― | ― | [Delegate].EndInvoke(t) | [Delegate].EndInvoke(t) | WaitHandle.WaitAll({t1.AsyncWaitHandle,t2.AsyncWaitHandle}) | WaitHandle.WaitAny({t1.AsyncWaitHandle,t2.AsyncWaitHandle}) | t.IsCompleted | |
System.Threading.Tasks.Task | Task.Run(...) | ― | ― | t.Wait() | t.Result | WaitAll(t1,t2,t3) | WaitAny(t1,t2,t3) | t.IsCompleted | |
WaitAll({t1,t2,t3}) | WaitAny({t1,t2,t3}) | ||||||||
WhenAll(t1,t2,t3).Wait() | WhenAny(t1,t2,t3).Wait() | ||||||||
WhenAll({t1,t2,t3}).Wait() | WhenAny({t1,t2,t3}).Wait() | ||||||||
Task (Async/Await) | ― | async Task<T>() | ― | await t | await t | Await WhenAll(t1,t2,t3) | Await WhenAny(t1,t2,t3) | ||
C++ | std::thread | std::thread(...) | ― | ― | t.join() | ― | ― | ― | ― |
std::future | std::async(std::launch::async,...) | ― | ― | t.wait() | t.get() | (boost::wait_for_all) | (boost::wait_for_any) | t.wait_for(std::chrono::seconds(0))==std::future_status::ready | |
D言語 | core.thread.Thread&ThreadGroup | t=new stdThread(...) t.start |
― | ― | t.join() | ― | [ThreadGroup{t1,t2,t3}].joinAll() | ― | t.inRunning |
Java | java.util.concurrent.Future | [ExecutorService].submit(...) | ― | ― | t.get() | t.get() | ― | ― | t.isDone() |
java.util.concurrent.CompletableFuture | ConpletableFuture.runAsync(...) | ― | t.thenRunAsync(()->...) | t.join() | t.get() | CompletableFuture.allOf(t1,t2,t3) | CompletableFuture.anyOf(t1,t2,t3) | t.isDone() | |
ConpletableFuture.supplyAsync(...) | t.thenApplyAsync(R->...) | CompletableFuture.allOf([]{t1,t2,t3}) | CompletableFuture.anyOf([]{t1,t2,t3}) | ||||||
Scala | scala.concurrent.Future&Promise | Future{...} | ― | t.foreach(R->) | Await.ready(t,[Time]) | Await.result(t,[Time]) | ― | (Promise) | t.isCompleted |
Go言語 | Goroutine&Channel | ch=make(chan ...) go func(){... ch<-;defer close(ch)} |
― | ― | <-ch | <-ch | ― | ― | ― |
sync.WaitGroup | [WaitGroup].Add([int]) [WaitGroup].Done() |
― | ― | [WaitGroup].Wait() | ― | [WaitGroup].wait() | [WaitGroup(add=1)].wait() | ― | |
Ruby | Threads&ThreadsWait | Thread.new() do ... end | ― | ― | t.join | ― | [ThreadsWait].all_waits | [ThreadsWait].next_wait | t.alive? |
ThreadsWait.all_waits(t1,t2,t3) | |||||||||
Python | threading.Thread | t=threading.Thread(target=...) t.start() |
― | ― | t.join() | ― | ― | ― | t.is_alive() |
concurrent.futures | [executor].submit(...[, args]) | ― | ― | t.result() | t.result() | concurrent.futures.wait([t1,t2,t3]) | concurrent.futures.wait([t1,t2,t3],return_when=concurrent.futures.FIRST_COMPLETED) | t.done() | |
asyncio (Async/Await) | asyncio.ensure_future(...) | async def() | ― | await t | await t | await asyncio.wait([t1,t2,t3]) | await asyncio.wait([t1,t2,t3],return_when=asyncio.FIRST_COMPLETED) | t.done() | |
await asyncio.gather(t1,t2,t3) | |||||||||
Scheme | gauche.threads | (thread-start!(make-thread ...)) | ― | ― | (thread-join! t) | (thread-join! t) | ― | ― | (thread-state t) |
Clojure | clojure/core.future | (future ...) | ― | ― | (deref t) @t |
(deref t) @t |
― | <promise> | (future-done? t) |
実行環境
JavaScript: node v6.9.1
TypeScript: tsc 1.8.10
VB.net: vbc 14.0.1055
C#: csc 4.6.1055.0
C++: cl Version 18.00.40629
D言語: dmd v2.066.1
Go言語: go 1.7.4
Java: java 1.8.0_112
Scala: scala 2.12.1
Ruby: ruby 2.0.0p481
Python3: python 3.5.1
Scheme: gosh 0.9.4
Clojure: Clojure-CLR 1.8.0