Last active
January 16, 2020 20:13
-
-
Save jakelandis/10519b9596888d8eb548d9fab28e4661 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Arrays; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.atomic.AtomicBoolean; | |
import java.util.function.Consumer; | |
class Scratch { | |
//for loop with sync or async actions processed in order with a post work step | |
public static void main(String[] args) throws InterruptedException { | |
String[] letters = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}; | |
ExecutorService executorService = Executors.newFixedThreadPool(10); | |
System.out.println("*************** Baseline ************"); | |
baseline(letters); | |
System.out.println("*************** Sync:1 ************"); | |
option1(letters, new SyncProcessor(), 0, Thread.currentThread()); | |
Thread.sleep(1000); | |
System.out.println("*************** Async:1 ************"); | |
option1(letters, new AsyncProcessor(executorService), 0, Thread.currentThread()); | |
Thread.sleep(1000); | |
System.out.println("*************** Sync:2 ************"); | |
option2(letters, new SyncProcessor(), 0, Thread.currentThread()); | |
Thread.sleep(1000); | |
System.out.println("*************** Async:2 ************"); | |
option2(letters, new AsyncProcessor(executorService), 0, Thread.currentThread()); | |
Thread.sleep(1000); | |
System.out.println("*************** Sync:3 ************"); | |
option3(letters, new SyncProcessor(), 0, Thread.currentThread()); | |
Thread.sleep(1000); | |
System.out.println("*************** Async:3 ************"); | |
option3(letters, new AsyncProcessor(executorService), 0, Thread.currentThread()); | |
Thread.sleep(1000); | |
executorService.shutdown(); | |
} | |
//properly ordered | |
public static void baseline(String[] letters) { | |
Arrays.stream(letters).forEach(System.out::println); | |
System.out.println("end"); | |
} | |
//sync - properly ordered, but deep stack | |
//async - properly ordered | |
public static void option1(String[] letters, Processor processor, int i, Thread mainThread) { | |
if (i == letters.length) { | |
System.out.println("end"); | |
return; | |
} | |
processor.process(letters[i], (l) -> { | |
System.out.println(l + " [" + mainThread.getStackTrace().length + "]"); | |
option1(letters, processor, i + 1, mainThread); | |
}); | |
} | |
//sync - properly ordered, no deep stack, but requires forking | |
//async - properly ordered | |
public static void option2(String[] letters, Processor processor, int i, Thread mainThread) { | |
if (i == letters.length) { | |
System.out.println("end"); | |
return; | |
} | |
final Thread thread = Thread.currentThread(); | |
processor.process(letters[i], (l) -> { | |
System.out.println(l + " [" + mainThread.getStackTrace().length + "]"); | |
if (thread == Thread.currentThread()) { | |
//synchronous, so need to fork the recursive call to avoid deep stack | |
new Thread(() -> option2(letters, processor, i + 1, mainThread)).start(); | |
} else { | |
option2(letters, processor, i + 1, mainThread); | |
} | |
}); | |
} | |
//credit: https://github.com/probakowski | |
//sync - properly ordered, no deep stack, no forking | |
//async - properly ordered | |
public static void option3(String[] letters, Processor processor, int i, Thread mainThread) { | |
for (; i < letters.length; i++) { | |
AtomicBoolean shouldContinueHere = new AtomicBoolean(); | |
int nextIndex = i + 1; | |
processor.process(letters[i], (l) -> { | |
System.out.println(l + " [" + mainThread.getStackTrace().length + "]"); | |
if (shouldContinueHere.getAndSet(true)) { | |
option3(letters, processor, nextIndex, mainThread); | |
} | |
}); | |
if (shouldContinueHere.getAndSet(true) == false) { | |
return; | |
} | |
} | |
if (i == letters.length) { | |
System.out.println("end"); | |
} | |
} | |
interface Processor { | |
void process(String letter, Consumer<String> handler); | |
} | |
static class SyncProcessor implements Processor { | |
public void process(String letter, Consumer<String> handler) { | |
handler.accept(letter); | |
} | |
} | |
static class AsyncProcessor implements Processor { | |
final ExecutorService executorService; | |
AsyncProcessor(ExecutorService executorService) { | |
this.executorService = executorService; | |
} | |
public void process(String letter, Consumer<String> handler) { | |
executorService.submit(() -> handler.accept(letter)); | |
} | |
} | |
} | |
/** | |
output: | |
*************** Baseline ************ | |
a | |
b | |
c | |
d | |
e | |
f | |
g | |
h | |
i | |
j | |
k | |
l | |
m | |
n | |
o | |
p | |
q | |
r | |
s | |
t | |
u | |
v | |
w | |
x | |
y | |
z | |
end | |
*************** Sync:1 ************ | |
a [5] | |
b [8] | |
c [11] | |
d [14] | |
e [17] | |
f [20] | |
g [23] | |
h [26] | |
i [29] | |
j [32] | |
k [35] | |
l [38] | |
m [41] | |
n [44] | |
o [47] | |
p [50] | |
q [53] | |
r [56] | |
s [59] | |
t [62] | |
u [65] | |
v [68] | |
w [71] | |
x [74] | |
y [77] | |
z [80] | |
end | |
*************** Async:1 ************ | |
a [2] | |
b [2] | |
c [2] | |
d [2] | |
e [2] | |
f [2] | |
g [2] | |
h [2] | |
i [2] | |
j [2] | |
k [2] | |
l [2] | |
m [2] | |
n [2] | |
o [2] | |
p [2] | |
q [2] | |
r [2] | |
s [2] | |
t [2] | |
u [2] | |
v [2] | |
w [2] | |
x [2] | |
y [2] | |
z [2] | |
end | |
*************** Sync:2 ************ | |
a [5] | |
b [2] | |
c [2] | |
d [2] | |
e [2] | |
f [2] | |
g [2] | |
h [2] | |
i [2] | |
j [2] | |
k [2] | |
l [2] | |
m [2] | |
n [2] | |
o [2] | |
p [2] | |
q [2] | |
r [2] | |
s [2] | |
t [2] | |
u [2] | |
v [2] | |
w [2] | |
x [2] | |
y [2] | |
z [2] | |
end | |
*************** Async:2 ************ | |
a [2] | |
b [2] | |
c [2] | |
d [2] | |
e [2] | |
f [2] | |
g [2] | |
h [2] | |
i [2] | |
j [2] | |
k [2] | |
l [2] | |
m [2] | |
n [2] | |
o [2] | |
p [2] | |
q [2] | |
r [2] | |
s [2] | |
t [2] | |
u [2] | |
v [2] | |
w [2] | |
x [2] | |
y [2] | |
z [2] | |
end | |
*************** Sync:3 ************ | |
a [5] | |
b [5] | |
c [5] | |
d [5] | |
e [5] | |
f [5] | |
g [5] | |
h [5] | |
i [5] | |
j [5] | |
k [5] | |
l [5] | |
m [5] | |
n [5] | |
o [5] | |
p [5] | |
q [5] | |
r [5] | |
s [5] | |
t [5] | |
u [5] | |
v [5] | |
w [5] | |
x [5] | |
y [5] | |
z [5] | |
end | |
*************** Async:3 ************ | |
a [2] | |
b [2] | |
c [2] | |
d [2] | |
e [2] | |
f [2] | |
g [2] | |
h [2] | |
i [2] | |
j [2] | |
k [2] | |
l [2] | |
m [2] | |
n [2] | |
o [2] | |
p [2] | |
q [2] | |
r [2] | |
s [2] | |
t [2] | |
u [2] | |
v [2] | |
w [2] | |
x [2] | |
y [2] | |
z [2] | |
end | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment