Concurrent computing: Difference between revisions
Content added Content deleted
(→{{header|Perl}}: added header pascal {trans|Delphi}}) |
Thundergnat (talk | contribs) (Revert to revision as of November 5) |
||
Line 1: | Line 1: | ||
{{task|Concurrency}} |
{{task|Concurrency}} |
||
[[Category:Basic language learning]] |
[[Category:Basic language learning]] |
||
;Task: |
;Task: |
||
Using either native language concurrency syntax or freely available libraries, write a program to display the strings "Enjoy" "Rosetta" "Code", one string per line, in random order. |
|||
Display the letters "A", "B", and "C" to a screen at the same time. |
|||
Concurrency syntax must use [[thread|threads]], tasks, co-routines, or whatever concurrency is called in your language. |
|||
The language's standard libraries are to be used, with external libraries only being used if the language does not allow this task to be completed with standard libraries. |
|||
<br><br> |
|||
(the task has been updated to avoid using programming-specific language, if a better description of displaying strings parallel-ly is found, please edit task) |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
<lang ada>with Ada.Text_IO, Ada.Numerics.Float_Random; |
<lang ada>with Ada.Text_IO, Ada.Numerics.Float_Random; |
||
Line 50: | Line 51: | ||
{{libheader|gomp}} |
{{libheader|gomp}} |
||
{{works with|OpenMP}} |
{{works with|OpenMP}} |
||
BaCon is a BASIC-to-C compiler. Assuming GCC compiler in this demonstration. Based on the C OpenMP source. |
|||
<lang freebasic>PRAGMA OPTIONS -fopenmp |
|||
<lang freebasic>' Concurrent computing using the OpenMP extension in GCC. Requires BaCon 3.6 or higher. |
|||
' Specify compiler flag |
|||
PRAGMA OPTIONS -fopenmp |
|||
' Sepcify linker flag |
|||
PRAGMA LDFLAGS -lgomp |
PRAGMA LDFLAGS -lgomp |
||
' Declare array with text |
|||
DECLARE str$[] = { "Enjoy", "Rosetta", "Code" } |
DECLARE str$[] = { "Enjoy", "Rosetta", "Code" } |
||
' Indicate MP optimization for FOR loop |
|||
PRAGMA omp parallel for num_threads(3) |
PRAGMA omp parallel for num_threads(3) |
||
' The actual FOR loop |
|||
FOR i = 0 TO 2 |
FOR i = 0 TO 2 |
||
PRINT str$[i] |
PRINT str$[i] |
||
NEXT |
NEXT |
||
</lang> |
|||
{{out}} |
|||
<pre>prompt$ bacon concurrent-computing |
|||
Converting 'concurrent-computing.bac'... done, 11 lines were processed in 0.002 seconds. |
|||
Compiling 'concurrent-computing.bac'... cc -fopenmp -c concurrent-computing.bac.c |
|||
cc -o concurrent-computing concurrent-computing.bac.o -lbacon -lm -lgomp |
|||
Done, program 'concurrent-computing' ready. |
|||
prompt$ ./concurrent-computing |
|||
Code |
|||
Enjoy |
|||
Rosetta</pre> |
|||
=={{header|BBC BASIC}}== |
=={{header|BBC BASIC}}== |
||
Line 94: | Line 120: | ||
=={{header|C}}== |
=={{header|C}}== |
||
{{works with|POSIX}} |
|||
{{libheader|pthread}} |
|||
<lang c>#include <stdio.h> |
<lang c>#include <stdio.h> |
||
#include <unistd.h> |
#include <unistd.h> |
||
#include <pthread.h> |
#include <pthread.h> |
||
pthread_mutex_t condm = PTHREAD_MUTEX_INITIALIZER; |
pthread_mutex_t condm = PTHREAD_MUTEX_INITIALIZER; |
||
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; |
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; |
||
int bang = 0; |
int bang = 0; |
||
#define WAITBANG() do { \ |
#define WAITBANG() do { \ |
||
pthread_mutex_lock(&condm); \ |
|||
while( bang == 0 ) \ |
|||
{ \ |
|||
pthread_cond_wait(&cond, &condm); \ |
|||
pthread_cond_wait(&cond, &condm); \ |
|||
} \ |
|||
} \ |
|||
pthread_mutex_unlock(&condm); \ |
|||
} while(0); |
pthread_mutex_unlock(&condm); } while(0);\ |
||
void * t_enjoy(void * p) { |
|||
void *t_enjoy(void *p) |
|||
WAITBANG(); |
|||
{ |
|||
printf("Enjoy\n"); |
|||
WAITBANG(); |
|||
printf("Enjoy\n"); |
|||
pthread_exit(0); |
|||
} |
} |
||
void * t_rosetta(void * p) { |
|||
void *t_rosetta(void *p) |
|||
WAITBANG(); |
|||
{ |
|||
printf("Rosetta\n"); |
|||
WAITBANG(); |
|||
printf("Rosetta\n"); |
|||
pthread_exit(0); |
|||
} |
} |
||
void * t_code(void * p) { |
|||
void *t_code(void *p) |
|||
WAITBANG(); |
|||
{ |
|||
printf("Code\n"); |
|||
WAITBANG(); |
|||
printf("Code\n"); |
|||
pthread_exit(0); |
|||
} |
} |
||
typedef void * (* threadfunc) (void *); |
|||
typedef void *(*threadfunc)(void *); |
|||
int main() { |
|||
int main() |
|||
{ |
|||
pthread_t a[3]; |
|||
int i; |
|||
threadfunc p[3] = {t_enjoy, t_rosetta, t_code}; |
|||
pthread_t a[3]; |
|||
for(i=0; i<3; i++) { |
|||
threadfunc p[3] = {t_enjoy, t_rosetta, t_code}; |
|||
pthread_create(&a[i], NULL, p[i], NULL); |
|||
for(i=0;i<3;i++) |
|||
{ |
|||
pthread_create(&a[i], NULL, p[i], NULL); |
|||
pthread_cond_broadcast(&cond); |
|||
} |
|||
for(i=0; i<3; i++) { |
|||
sleep(1); |
|||
pthread_join(a[i], NULL); |
|||
bang = 1; |
|||
pthread_cond_broadcast(&cond); |
|||
for(i=0;i<3;i++) |
|||
{ |
|||
pthread_join(a[i], NULL); |
|||
} |
|||
}</lang> |
|||
'''Note''': since threads are created one after another, it is likely that the execution of their code follows the order of creation. To make this less evident, I've added the ''bang'' idea using condition: the thread really executes their code once the gun bang is heard. Nonetheless, I still obtain the same order of creation (Enjoy, Rosetta, Code), and maybe it is because of the order locks are acquired. The only way to obtain randomness seems to be to add random wait in each thread (or wait for special cpu load condition) |
|||
===OpenMP=== |
|||
Compile with <code>gcc -std=c99 -fopenmp</code>: |
|||
<lang C>#include <stdio.h> |
|||
#include <omp.h> |
|||
int main() |
|||
{ |
|||
const char *str[] = { "Enjoy", "Rosetta", "Code" }; |
|||
#pragma omp parallel for num_threads(3) |
|||
for (int i = 0; i < 3; i++) |
|||
printf("%s\n", str[i]); |
|||
return 0; |
|||
}</lang> |
}</lang> |
||
=={{header|c sharp|C#}}== |
=={{header|c sharp|C#}}== |
||
===With Threads=== |
===With Threads=== |
||
<lang csharp> |
<lang csharp> |
||
static |
static Random tRand = new Random(); |
||
Thread t = new Thread(new ParameterizedThreadStart(WriteText)); |
|||
static void Main(string[] args) |
|||
t.Start("Enjoy"); |
|||
{ |
|||
t = new Thread(new ParameterizedThreadStart(WriteText)); |
|||
Thread t = new Thread(new ParameterizedThreadStart(WriteText)); |
|||
t.Start("Rosetta"); |
|||
t.Start("Enjoy"); |
|||
t = new Thread(new ParameterizedThreadStart(WriteText)); |
|||
t.Start("Code"); |
|||
t = new Thread(new ParameterizedThreadStart(WriteText)); |
|||
Console.ReadLine(); |
|||
t.Start("Rosetta"); |
|||
t = new Thread(new ParameterizedThreadStart(WriteText)); |
|||
t.Start("Code"); |
|||
Console.ReadLine(); |
|||
} |
} |
||
private static void WriteText(object p) { |
|||
private static void WriteText(object p) |
|||
Thread.Sleep(tRand.Next(1000, 4000)); |
|||
{ |
|||
Console.WriteLine(p); |
|||
Thread.Sleep(tRand.Next(1000, 4000)); |
|||
}</lang> |
|||
Console.WriteLine(p); |
|||
} |
|||
</lang> |
|||
An example result: |
|||
<pre> |
|||
Enjoy |
|||
Code |
|||
Rosetta |
|||
</pre> |
|||
===With Tasks=== |
===With Tasks=== |
||
{{works with|C sharp|7.1}} |
{{works with|C sharp|7.1}} |
||
<lang csharp>using System; |
<lang csharp>using System; |
||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||
public class Program { |
|||
public class Program |
|||
{ |
|||
static async Task Main() { |
static async Task Main() { |
||
Task t1 = Task.Run(() => Console.WriteLine("Enjoy")); |
Task t1 = Task.Run(() => Console.WriteLine("Enjoy")); |
||
Task t2 = Task.Run(() => Console.WriteLine("Rosetta")); |
Task t2 = Task.Run(() => Console.WriteLine("Rosetta")); |
||
Task t3 = Task.Run(() => Console.WriteLine("Code")); |
Task t3 = Task.Run(() => Console.WriteLine("Code")); |
||
await Task.WhenAll(t1, t2, t3); |
await Task.WhenAll(t1, t2, t3); |
||
} |
} |
||
Line 169: | Line 247: | ||
<lang csharp>using System; |
<lang csharp>using System; |
||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||
public class Program { |
|||
public class Program |
|||
{ |
|||
static void Main() => Parallel.ForEach(new[] {"Enjoy", "Rosetta", "Code"}, s => Console.WriteLine(s)); |
static void Main() => Parallel.ForEach(new[] {"Enjoy", "Rosetta", "Code"}, s => Console.WriteLine(s)); |
||
}</lang> |
}</lang> |
||
Line 176: | Line 256: | ||
{{works with|C++11}} |
{{works with|C++11}} |
||
The following example compiles with GCC 4.7. |
The following example compiles with GCC 4.7. |
||
<code>g++ -std=c++11 -D_GLIBCXX_USE_NANOSLEEP -o concomp concomp.cpp</code> |
<code>g++ -std=c++11 -D_GLIBCXX_USE_NANOSLEEP -o concomp concomp.cpp</code> |
||
<lang cpp>#include <thread> |
<lang cpp>#include <thread> |
||
#include <iostream> |
#include <iostream> |
||
Line 182: | Line 264: | ||
#include <random> |
#include <random> |
||
#include <chrono> |
#include <chrono> |
||
int main() { |
|||
int main() |
|||
std::random_device rd; |
|||
{ |
|||
std::mt19937 eng(rd()); |
|||
std::random_device rd; |
|||
std::uniform_int_distribution<> dist(1,1000); |
|||
std::mt19937 eng(rd()); // mt19937 generator with a hardware random seed. |
|||
std::vector<std::thread> threads; |
|||
std::uniform_int_distribution<> dist(1,1000); |
|||
for (const auto& str: {"Enjoy\n", "Rosetta\n", "Code\n"}) { |
|||
std::vector<std::thread> threads; |
|||
std::chrono::milliseconds duration(dist(eng)); |
|||
threads.emplace_back([str, duration]() { |
|||
for(const auto& str: {"Enjoy\n", "Rosetta\n", "Code\n"}) { |
|||
std::this_thread::sleep_for(duration); |
|||
// between 1 and 1000ms per our distribution |
|||
std::chrono::milliseconds duration(dist(eng)); |
|||
}); |
|||
} |
|||
threads.emplace_back([str, duration](){ |
|||
for (auto& t: threads) |
|||
std::this_thread::sleep_for(duration); |
|||
std::cout << str; |
|||
}); |
|||
} |
|||
for(auto& t: threads) t.join(); |
|||
return 0; |
|||
}</lang> |
|||
Output: |
|||
<pre>Enjoy |
|||
Code |
|||
Rosetta</pre> |
|||
{{libheader|Microsoft Parallel Patterns Library (PPL)}} |
|||
<lang cpp>#include <iostream> |
|||
#include <ppl.h> // MSVC++ |
|||
void a(void) { std::cout << "Eat\n"; } |
|||
void b(void) { std::cout << "At\n"; } |
|||
void c(void) { std::cout << "Joe's\n"; } |
|||
int main() |
|||
{ |
|||
// function pointers |
|||
Concurrency::parallel_invoke(&a, &b, &c); |
|||
// C++11 lambda functions |
|||
Concurrency::parallel_invoke( |
|||
[]{ std::cout << "Enjoy\n"; }, |
|||
[]{ std::cout << "Rosetta\n"; }, |
|||
[]{ std::cout << "Code\n"; } |
|||
); |
|||
return 0; |
return 0; |
||
}</lang> |
}</lang> |
||
Output: |
|||
<pre> |
|||
Joe's |
|||
Eat |
|||
At |
|||
Enjoy |
|||
Code |
|||
Rosetta |
|||
</pre> |
|||
=={{header|Cind}}== |
=={{header|Cind}}== |
||
Line 485: | Line 610: | ||
=={{header|Elixir}}== |
=={{header|Elixir}}== |
||
<lang Elixir>defmodule Concurrent do |
<lang Elixir>defmodule Concurrent do |
||
def computing(xs) do |
|||
Enum.each(xs, fn x -> |
|||
spawn(fn -> |
|||
Process.sleep(:rand.uniform(1000)) |
|||
IO.puts x |
|||
end) |
|||
end) |
|||
Process.sleep(1000) |
|||
end |
|||
end |
|||
Process.sleep(1000) |
|||
end |
|||
end |
end |
||
Concurrent.computing ["A", "B", "C"]</lang> |
|||
Concurrent.computing ["Enjoy", "Rosetta", "Code"]</lang> |
|||
{{out}} |
|||
<pre> |
|||
Rosetta |
|||
Code |
|||
Enjoy |
|||
</pre> |
|||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
Line 530: | Line 661: | ||
puts(1,'\n') |
puts(1,'\n') |
||
end procedure |
end procedure |
||
atom task1,task2,task3 |
atom task1,task2,task3 |
||
task1 = task_create(routine_id("echo"),{"A"}) |
|||
task1 = task_create(routine_id("echo"),{"Enjoy"}) |
|||
task_schedule(task1,1) |
task_schedule(task1,1) |
||
task2 = task_create(routine_id("echo"),{"B"}) |
|||
task2 = task_create(routine_id("echo"),{"Rosetta"}) |
|||
task_schedule(task2,1) |
task_schedule(task2,1) |
||
task3 = task_create(routine_id("echo"),{"C"}) |
|||
task3 = task_create(routine_id("echo"),{"Code"}) |
|||
task_schedule(task3,1) |
task_schedule(task3,1) |
||
task_yield()</lang> |
task_yield()</lang> |
||
Output: |
|||
Code |
|||
Rosetta |
|||
Enjoy |
|||
=={{header|F_Sharp|F#}}== |
=={{header|F_Sharp|F#}}== |
||
Line 632: | Line 773: | ||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
<lang freebasic> |
<lang freebasic>' FB 1.05.0 Win64 |
||
' Compiled with -mt switch (to use threadsafe runtiume) |
|||
Print "A" |
|||
' The 'ThreadCall' functionality in FB is based internally on LibFFi (see [https://github.com/libffi/libffi/blob/master/LICENSE] for license) |
|||
Sub thread1() |
|||
Print "Enjoy" |
|||
End Sub |
End Sub |
||
Sub thread2() |
Sub thread2() |
||
Print "Rosetta" |
|||
End Sub |
End Sub |
||
Sub thread3() |
Sub thread3() |
||
Print "Code" |
|||
End Sub |
End Sub |
||
Print "Press any key to print next batch of 3 strings or ESC to quit" |
Print "Press any key to print next batch of 3 strings or ESC to quit" |
||
Print |
Print |
||
Do |
Do |
||
Dim t1 As Any Ptr = ThreadCall thread1 |
|||
Dim t2 As Any Ptr = ThreadCall thread2 |
|||
Dim t3 As Any Ptr = ThreadCall thread3 |
|||
ThreadWait t1 |
|||
ThreadWait t2 |
|||
ThreadWait t3 |
|||
Print |
|||
Sleep |
|||
Loop While Inkey <> Chr(27)</lang> |
Loop While Inkey <> Chr(27)</lang> |
||
Sample output |
|||
{{out}} |
|||
<pre> |
|||
Press any key to print next batch of 3 strings or ESC to quit |
|||
Enjoy |
|||
Code |
|||
Rosetta |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
Line 716: | Line 880: | ||
multiple channel operations. |
multiple channel operations. |
||
<lang go>package main |
<lang go>package main |
||
import "fmt" |
import "fmt" |
||
func main() { |
func main() { |
||
w1 := make(chan bool, 1) |
w1 := make(chan bool, 1) |
||
Line 729: | Line 895: | ||
select { |
select { |
||
case <-w1: |
case <-w1: |
||
fmt.Println(" |
fmt.Println("Enjoy") |
||
case <-w2: |
case <-w2: |
||
fmt.Println(" |
fmt.Println("Rosetta") |
||
case <-w3: |
case <-w3: |
||
fmt.Println(" |
fmt.Println("Code") |
||
} |
} |
||
} |
} |
||
} |
} |
||
}</lang> |
}</lang> |
||
Output: |
|||
<pre> |
|||
Code |
|||
Rosetta |
|||
Enjoy |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
Rosetta |
|||
Enjoy |
|||
Code |
|||
</pre> |
|||
=={{header|Groovy}}== |
=={{header|Groovy}}== |
||
Line 877: | Line 1,057: | ||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
<lang scala> |
<lang scala>// version 1.1.2 |
||
import java.util.concurrent.CyclicBarrier |
|||
class DelayedMessagePrinter(val barrier: CyclicBarrier, val msg: String) : Runnable { |
class DelayedMessagePrinter(val barrier: CyclicBarrier, val msg: String) : Runnable { |
||
override fun run() { |
override fun run() { |
||
Line 884: | Line 1,067: | ||
} |
} |
||
} |
} |
||
fun main(args: Array<String>) { |
fun main(args: Array<String>) { |
||
val msgs = listOf("Enjoy", "Rosetta", "Code") |
val msgs = listOf("Enjoy", "Rosetta", "Code") |
||
Line 889: | Line 1,073: | ||
for (msg in msgs) Thread(DelayedMessagePrinter(barrier, msg)).start() |
for (msg in msgs) Thread(DelayedMessagePrinter(barrier, msg)).start() |
||
}</lang> |
}</lang> |
||
{{out}} |
|||
Sample output: |
|||
<pre> |
|||
Code |
|||
Rosetta |
|||
Enjoy |
|||
</pre> |
|||
=={{header|LFE}}== |
=={{header|LFE}}== |
||
Line 1,042: | Line 1,234: | ||
=={{header|Neko}}== |
=={{header|Neko}}== |
||
<lang ActionScript> |
<lang ActionScript>/** |
||
Concurrent computing, in Neko |
|||
*/ |
|||
var thread_create = $loader.loadprim("std@thread_create", 2); |
|||
var subtask = function(message) { |
var subtask = function(message) { |
||
$print(message, "\n"); |
|||
} |
} |
||
/* The thread functions happen so fast as to look sequential */ |
|||
thread_create(subtask, "Enjoy"); |
thread_create(subtask, "Enjoy"); |
||
thread_create(subtask, "Rosetta"); |
thread_create(subtask, "Rosetta"); |
||
thread_create(subtask, "Code"); |
thread_create(subtask, "Code"); |
||
/* slow things down */ |
|||
var sys_sleep = $loader.loadprim("std@sys_sleep", 1); |
var sys_sleep = $loader.loadprim("std@sys_sleep", 1); |
||
var random_new = $loader.loadprim("std@random_new", 0); |
var random_new = $loader.loadprim("std@random_new", 0); |
||
var random_int = $loader.loadprim("std@random_int", 2); |
var random_int = $loader.loadprim("std@random_int", 2); |
||
var randomsleep = function(message) { |
var randomsleep = function(message) { |
||
var r = random_new(); |
|||
var sleep = random_int(r, 3); |
|||
sys_sleep(sleep); |
|||
$print(message, "\n"); |
|||
} |
} |
||
$print("\nWith random delays\n"); |
$print("\nWith random delays\n"); |
||
thread_create(randomsleep, " |
thread_create(randomsleep, "Enjoy"); |
||
thread_create(randomsleep, " |
thread_create(randomsleep, "Rosetta"); |
||
thread_create(randomsleep, " |
thread_create(randomsleep, "Code"); |
||
/* Let the threads complete */ |
|||
sys_sleep(4);</lang> |
sys_sleep(4);</lang> |
||
{{out}} |
|||
<pre>prompt$ nekoc threading.neko |
|||
prompt$ neko threading |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
With random delays |
|||
Rosetta |
|||
Enjoy |
|||
Code</pre> |
|||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
Line 1,233: | Line 1,450: | ||
See also [http://pari.math.u-bordeaux1.fr/Events/PARI2012/talks/pareval.pdf Bill Allombert's slides on parallel programming in GP]. |
See also [http://pari.math.u-bordeaux1.fr/Events/PARI2012/talks/pareval.pdf Bill Allombert's slides on parallel programming in GP]. |
||
=={{header|Pascal}}== |
|||
{{trans|Delphi}} modified for linux. Using simple running thread-counter to circumvent WaitForMultipleObjects.<BR> |
|||
Output of difference of sleep time and true sleep time ( running with 0..1999 threads you see once a while 1) |
|||
<lang pascal>program ConcurrentComputing; |
|||
{$IFdef FPC} |
|||
{$MODE DELPHI} |
|||
{$ELSE} |
|||
{$APPTYPE CONSOLE} |
|||
{$ENDIF} |
|||
uses |
|||
{$IFDEF UNIX} |
|||
cthreads, |
|||
{$ENDIF} |
|||
SysUtils, Classes; |
|||
type |
|||
TRandomThread = class(TThread) |
|||
private |
|||
FString: string; |
|||
T0 : Uint64; |
|||
protected |
|||
procedure Execute; override; |
|||
public |
|||
constructor Create(const aString: string); overload; |
|||
end; |
|||
const |
|||
MyStrings: array[0..2] of String = ('Enjoy ','Rosetta ','Code '); |
|||
var |
|||
gblRunThdCnt : NativeInt = 0; |
|||
constructor TRandomThread.Create(const aString: string); |
|||
begin |
|||
inherited Create(False); |
|||
FreeOnTerminate := True; |
|||
FString := aString; |
|||
inc(gblRunThdCnt); |
|||
end; |
|||
procedure TRandomThread.Execute; |
|||
var |
|||
i : NativeInt; |
|||
begin |
|||
i := Random(300); |
|||
T0 := GettickCount64; |
|||
Sleep(i); |
|||
//output of difference in time |
|||
Writeln(FString,i:4,GettickCount64-T0 -i:2); |
|||
dec(gblRunThdCnt); |
|||
end; |
|||
var |
|||
lThreadArray: Array[0..9] of THandle; |
|||
i : NativeInt; |
|||
begin |
|||
Randomize; |
|||
gblRunThdCnt := 0; |
|||
For i := low(lThreadArray) to High(lThreadArray) do |
|||
lThreadArray[i] := TRandomThread.Create(Format('%9s %4d',[myStrings[Random(3)],i])).Handle; |
|||
while gblRunThdCnt > 0 do |
|||
sleep(125); |
|||
end.</lang> |
|||
{{out}} |
|||
<pre> |
|||
Enjoy 4 16 0 |
|||
Code 0 22 0 |
|||
Code 1 32 0 |
|||
Rosetta 7 117 0 |
|||
Enjoy 2 137 0 |
|||
Code 6 214 0 |
|||
Code 5 252 0 |
|||
Enjoy 3 299 0</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
{{libheader|Time::HiRes}} |
{{libheader|Time::HiRes}} |
||
Line 1,366: | Line 1,512: | ||
Using POSIX threads: |
Using POSIX threads: |
||
<lang Pike>int main() { |
<lang Pike>int main() { |
||
// Start threads and wait for them to finish |
|||
({ |
|||
({ |
|||
Thread.Thread(write, "A"), |
|||
Thread.Thread(write, "Enjoy\n"), |
|||
Thread.Thread(write, "Rosetta\n"), |
|||
Thread.Thread(write, "Code\n") |
|||
}) -> wait(); |
|||
})->wait(); |
|||
// Exit program |
|||
exit(0); |
|||
}</lang> |
}</lang> |
||
Output: |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
Using Pike's backend: |
Using Pike's backend: |
||
<lang Pike>int main(int argc, array argv) |
<lang Pike>int main(int argc, array argv) |
||
{ |
|||
call_out(write, random(1.0), "A"); |
|||
call_out(write, random(1.0), " |
call_out(write, random(1.0), "Enjoy\n"); |
||
call_out(write, random(1.0), " |
call_out(write, random(1.0), "Rosetta\n"); |
||
call_out(write, random(1.0), "Code\n"); |
|||
call_out(exit, 1, 0); |
call_out(exit, 1, 0); |
||
return -1; // return -1 starts the backend which makes Pike run until exit() is called. |
|||
return -1; |
|||
}</lang> |
}</lang> |
||
Output: |
|||
Rosetta |
|||
Code |
|||
Enjoy |
|||
=={{header|PowerShell}}== |
=={{header|PowerShell}}== |
||
Line 1,461: | Line 1,620: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
{{works with|Python|3.7}} |
|||
Using asyncio module (I know almost nothing about it, so feel free to improve it :-)): |
|||
<lang python>import asyncio |
<lang python>import asyncio |
||
async def print_(string: str) -> None: |
async def print_(string: str) -> None: |
||
print(string) |
print(string) |
||
async def main(): |
async def main(): |
||
strings = ['Enjoy', 'Rosetta', 'Code'] |
strings = ['Enjoy', 'Rosetta', 'Code'] |
||
coroutines = map(print_, strings) |
coroutines = map(print_, strings) |
||
await asyncio.gather(*coroutines) |
await asyncio.gather(*coroutines) |
||
if __name__ == '__main__': |
if __name__ == '__main__': |
||
asyncio.run(main())</lang> |
asyncio.run(main())</lang> |
||
{{works with|Python|3.2}} |
|||
Using the new to Python 3.2 [http://docs.python.org/release/3.2/library/concurrent.futures.html concurrent.futures library] and choosing to use processes over threads; the example will use up to as many processes as your machine has cores. This doesn't however guarantee an order of sub-process results. |
|||
<lang python>Python 3.2 (r32:88445, Feb 20 2011, 21:30:00) [MSC v.1500 64 bit (AMD64)] on win 32 |
|||
Type "help", "copyright", "credits" or "license" for more information. |
|||
>>> from concurrent import futures |
|||
>>> with futures.ProcessPoolExecutor() as executor: |
|||
... _ = list(executor.map(print, 'Enjoy Rosetta Code'.split())) |
|||
... |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
>>></lang> |
|||
{{works with|Python|2.5}} |
|||
<lang python>import threading |
|||
import random |
|||
def echo(text): |
|||
print(text) |
|||
threading.Timer(random.random(), echo, ("Enjoy",)).start() |
|||
threading.Timer(random.random(), echo, ("Rosetta",)).start() |
|||
threading.Timer(random.random(), echo, ("Code",)).start()</lang> |
|||
Or, by using a for loop to start one thread per list entry, where our list is our set of source strings: |
|||
<lang python>import threading |
|||
import random |
|||
def echo(text): |
|||
print(text) |
|||
for text in ["Enjoy", "Rosetta", "Code"]: |
|||
threading.Timer(random.random(), echo, (text,)).start()</lang> |
|||
=== threading.Thread === |
=== threading.Thread === |
||
<lang python>import random, sys, time |
<lang python>import random, sys, time |
||
import threading |
import threading |
||
lock = threading.Lock() |
lock = threading.Lock() |
||
def echo(s): |
def echo(s): |
||
time.sleep(1e-2*random.random()) |
time.sleep(1e-2*random.random()) |
||
Line 1,480: | Line 1,687: | ||
sys.stdout.write(s) |
sys.stdout.write(s) |
||
sys.stdout.write('\n') |
sys.stdout.write('\n') |
||
for line in 'Enjoy Rosetta Code'.split(): |
for line in 'Enjoy Rosetta Code'.split(): |
||
threading.Thread(target=echo, args=(line,)).start()</lang> |
threading.Thread(target=echo, args=(line,)).start()</lang> |
||
=== multiprocessing === |
=== multiprocessing === |
||
{{works with|Python|2.6}} |
|||
<lang python>from __future__ import print_function |
<lang python>from __future__ import print_function |
||
from multiprocessing import Pool |
from multiprocessing import Pool |
||
def main(): |
def main(): |
||
p = Pool() |
p = Pool() |
||
p.map(print, 'Enjoy Rosetta Code'.split()) |
p.map(print, 'Enjoy Rosetta Code'.split()) |
||
if __name__=="__main__": |
if __name__=="__main__": |
||
main()</lang> |
main()</lang> |
||
=== twisted === |
|||
<lang python>import random |
|||
from twisted.internet import reactor, task, defer |
|||
from twisted.python.util import println |
|||
delay = lambda: 1e-4*random.random() |
|||
d = defer.DeferredList([task.deferLater(reactor, delay(), println, line) |
|||
for line in 'Enjoy Rosetta Code'.split()]) |
|||
d.addBoth(lambda _: reactor.stop()) |
|||
reactor.run()</lang> |
|||
=== gevent === |
|||
<lang python>from __future__ import print_function |
|||
import random |
|||
import gevent |
|||
delay = lambda: 1e-4*random.random() |
|||
gevent.joinall([gevent.spawn_later(delay(), print, line) |
|||
for line in 'Enjoy Rosetta Code'.split()])</lang> |
|||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
Line 1,505: | Line 1,738: | ||
(formerly Perl 6) |
(formerly Perl 6) |
||
{{works with|Rakudo|2018.9}} |
{{works with|Rakudo|2018.9}} |
||
<lang perl6>my @words = < |
<lang perl6>my @words = <Enjoy Rosetta Code>; |
||
@words.race(:batch(1)).map: { sleep rand; say $_ };</lang> |
@words.race(:batch(1)).map: { sleep rand; say $_ };</lang> |
||
{{out}} |
|||
<pre>Code |
|||
Rosetta |
|||
Enjoy</pre> |
|||
=={{header|Raven}}== |
=={{header|Raven}}== |
||
Line 1,583: | Line 1,820: | ||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
A very basic threading support is provided by the '''Block.fork()''' method: |
|||
<lang ruby>var a = <Enjoy Rosetta Code> |
<lang ruby>var a = <Enjoy Rosetta Code> |
||
a.map{|str| { |
|||
a.map{|str| |
|||
Sys.sleep(1.rand) |
|||
{ Sys.sleep(1.rand) |
|||
say str |
say str |
||
}.fork |
}.fork |
||
}.map{|thr| thr.wait}</lang> |
}.map{|thr| thr.wait }</lang> |
||
{{out}} |
|||
<pre> |
|||
Enjoy |
|||
Code |
|||
Rosetta |
|||
</pre> |
|||
=={{header|Swift}}== |
=={{header|Swift}}== |
||
Using Grand Central Dispatch with concurrent queues. |
Using Grand Central Dispatch with concurrent queues. |
||
<lang Swift>import Foundation |
<lang Swift>import Foundation |
||
let myList = ["A", "B", "C"] |
|||
let myList = ["Enjoy", "Rosetta", "Code"] |
|||
for word in myList { |
for word in myList { |
||
dispatch_async(dispatch_get_global_queue(0, 0)) { |
dispatch_async(dispatch_get_global_queue(0, 0)) { |
||
Line 1,599: | Line 1,847: | ||
} |
} |
||
} |
} |
||
dispatch_main()</lang> |
dispatch_main()</lang> |
||
{{out}} |
|||
<pre> |
|||
2015-02-05 10:15:01.831 rosettaconcurrency[1917:37905] Code |
|||
2015-02-05 10:15:01.831 rosettaconcurrency[1917:37902] Enjoy |
|||
2015-02-05 10:15:01.831 rosettaconcurrency[1917:37904] Rosetta |
|||
</pre> |
|||
=={{header|Standard ML}}== |
=={{header|Standard ML}}== |
||
Line 1,714: | Line 1,969: | ||
End Module</lang> |
End Module</lang> |
||
===Alternative version=== |
===Alternative version=== |
||
[https://tio.run/##TY9PC8IwDMXv@xRhpw60oODFm@gEQUWs4Llbg6t0zWjrn3362bmBvssjCfnl5VlMS3LYdbu6IRc8iNYHrPmlciiVtrfkQOphEAabJRC10TU4q2Dl4YgvOEurqGbZdyYeBRyktmPZ6ySdNAYN35LLZVmxNLd3auFMHkOQsCaFKReN0YGlkGaTHsL8D9BrCMSFQWxYPM6P@A5svsgyWEaC9WSQX50OuNcW/7fzmDQCh8ZYJL0PL3XdBw Try It Online!] |
|||
<lang vbnet>Imports System.Threading |
<lang vbnet>Imports System.Threading |
||
Module Module1 |
Module Module1 |
||
Line 1,723: | Line 1,979: | ||
End Sub |
End Sub |
||
End Module</lang> |
End Module</lang> |
||
{{out}} |
|||
<pre>Rosetta |
|||
Enjoy |
|||
Code</pre> |
|||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
<lang ecmascript>import "random" for Random |
<lang ecmascript>import "random" for Random |
||
var words = ["Enjoy", "Rosetta", "Code"] |
var words = ["Enjoy", "Rosetta", "Code"] |
||
var rand = Random.new() |
var rand = Random.new() |
||
Line 1,743: | Line 2,004: | ||
System.print() |
System.print() |
||
}</lang> |
}</lang> |
||
{{out}} |
|||
Sample run: |
|||
<pre> |
|||
Enjoy |
|||
Code |
|||
Rosetta |
|||
Code |
|||
Enjoy |
|||
Rosetta |
|||
Rosetta |
|||
Enjoy |
|||
Code |
|||
</pre> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
<lang zkl>fcn{println("Enjoy")}.launch(); |
<lang zkl>fcn{println("Enjoy")}.launch(); // thread |
||
fcn{println("Rosetta")}.strand(); |
fcn{println("Rosetta")}.strand(); // co-op thread |
||
fcn{println("Code")}.future();</lang> |
fcn{println("Code")}.future(); // another thread type</lang> |
||
{{out}} |
|||
<pre> |
|||
Rosetta |
|||
Code |
|||
Enjoy |
|||
</pre> |
|||
{{omit from|AWK}} |
|||
{{omit from|bc}} |
|||
{{omit from|Brlcad}} |
|||
{{omit from|dc}} |
|||
{{omit from|GUISS}} |
|||
{{omit from|Lilypond}} |
|||
{{omit from|Maxima}} |
|||
{{Omit From|Metafont}} |
|||
{{omit from|Openscad}} |
|||
{{omit from|TI-83 BASIC|Does not have concurrency or background processes.}} |
|||
{{omit from|TI-89 BASIC|Does not have concurrency or background processes.}} |
|||
{{omit from|TPP}} |
|||
{{omit from|Vim Script}} |
|||
{{omit from|ZX Spectrum Basic}} |
|||
{{omit from|Axe}} |