September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -1,119 +0,0 @@
|
|||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
public class AtomicUpdates
|
||||
{
|
||||
public static class Buckets
|
||||
{
|
||||
private final int[] data;
|
||||
|
||||
public Buckets(int[] data)
|
||||
{
|
||||
this.data = data.clone();
|
||||
}
|
||||
|
||||
public int getBucket(int index)
|
||||
{
|
||||
synchronized (data)
|
||||
{ return data[index]; }
|
||||
}
|
||||
|
||||
public int transfer(int srcBucketIndex, int destBucketIndex, int amount)
|
||||
{
|
||||
if (amount == 0)
|
||||
return 0;
|
||||
// Negative transfers will happen in the opposite direction
|
||||
if (amount < 0)
|
||||
{
|
||||
int tempIndex = srcBucketIndex;
|
||||
srcBucketIndex = destBucketIndex;
|
||||
destBucketIndex = tempIndex;
|
||||
amount = -amount;
|
||||
}
|
||||
synchronized (data)
|
||||
{
|
||||
if (amount > data[srcBucketIndex])
|
||||
amount = data[srcBucketIndex];
|
||||
if (amount <= 0)
|
||||
return 0;
|
||||
data[srcBucketIndex] -= amount;
|
||||
data[destBucketIndex] += amount;
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getBuckets()
|
||||
{
|
||||
synchronized (data)
|
||||
{ return data.clone(); }
|
||||
}
|
||||
}
|
||||
|
||||
public static int getTotal(int[] values)
|
||||
{
|
||||
int totalValue = 0;
|
||||
for (int i = values.length - 1; i >= 0; i--)
|
||||
totalValue += values[i];
|
||||
return totalValue;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
final int NUM_BUCKETS = 10;
|
||||
Random rnd = new Random();
|
||||
final int[] values = new int[NUM_BUCKETS];
|
||||
for (int i = 0; i < values.length; i++)
|
||||
values[i] = rnd.nextInt(10);
|
||||
System.out.println("Initial Array: " + getTotal(values) + " " + Arrays.toString(values));
|
||||
final Buckets buckets = new Buckets(values);
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run()
|
||||
{
|
||||
Random r = new Random();
|
||||
while (true)
|
||||
{
|
||||
int srcBucketIndex = r.nextInt(NUM_BUCKETS);
|
||||
int destBucketIndex = r.nextInt(NUM_BUCKETS);
|
||||
int amount = (buckets.getBucket(srcBucketIndex) - buckets.getBucket(destBucketIndex)) >> 1;
|
||||
if (amount != 0)
|
||||
buckets.transfer(srcBucketIndex, destBucketIndex, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
).start();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run()
|
||||
{
|
||||
Random r = new Random();
|
||||
while (true)
|
||||
{
|
||||
int srcBucketIndex = r.nextInt(NUM_BUCKETS);
|
||||
int destBucketIndex = r.nextInt(NUM_BUCKETS);
|
||||
int srcBucketAmount = buckets.getBucket(srcBucketIndex);
|
||||
int destBucketAmount = buckets.getBucket(destBucketIndex);
|
||||
int amount = r.nextInt(srcBucketAmount + destBucketAmount + 1) - destBucketAmount;
|
||||
if (amount != 0)
|
||||
buckets.transfer(srcBucketIndex, destBucketIndex, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
).start();
|
||||
|
||||
while (true)
|
||||
{
|
||||
long nextPrintTime = System.currentTimeMillis() + 3000;
|
||||
long curTime;
|
||||
while ((curTime = System.currentTimeMillis()) < nextPrintTime)
|
||||
{
|
||||
try
|
||||
{ Thread.sleep(nextPrintTime - curTime); }
|
||||
catch (InterruptedException e)
|
||||
{ }
|
||||
}
|
||||
int[] bucketValues = buckets.getBuckets();
|
||||
System.out.println("Current values: " + getTotal(bucketValues) + " " + Arrays.toString(bucketValues));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface Buckets {
|
||||
public static Buckets new_(int[] data) {
|
||||
return $.new_(data);
|
||||
}
|
||||
public static void main(String... arguments) {
|
||||
$.main(arguments);
|
||||
}
|
||||
public int[] getBuckets();
|
||||
|
||||
public int getBucket(int index);
|
||||
|
||||
public int transfer(int srcBucketIndex, int destBucketIndex, int amount);
|
||||
|
||||
public enum $ {
|
||||
$$;
|
||||
|
||||
private static Buckets new_(int[] data) {
|
||||
return (FunctionalBuckets) function -> {
|
||||
synchronized (data) {
|
||||
return Optional.of(data)
|
||||
.map(function)
|
||||
.filter(output -> output != data)
|
||||
.orElseGet(() -> data.clone())
|
||||
;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void main(String... arguments) {
|
||||
Stream.of(new Random())
|
||||
.parallel()
|
||||
.map(r -> r.ints($.NUM_BUCKETS, 0, NUM_BUCKETS))
|
||||
.map(IntStream::toArray)
|
||||
.peek(bucketValues -> Stream.of(bucketValues)
|
||||
.map(values -> "Initial values: " + getTotal(values) + " " + Arrays.toString(values))
|
||||
.forEach(System.out::println)
|
||||
)
|
||||
.map(Buckets::new_)
|
||||
.forEach(
|
||||
Stream.<Consumer<Buckets>>of(
|
||||
$::processBuckets,
|
||||
$::displayBuckets
|
||||
).reduce($ -> {}, Consumer::andThen)
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private static interface FunctionalBuckets extends Buckets {
|
||||
public Object untypedUseData(Function<int[], Object> function);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public default <OUTPUT> OUTPUT useData(Function<int[], OUTPUT> function) {
|
||||
return (OUTPUT) untypedUseData(function::apply);
|
||||
}
|
||||
|
||||
@Override
|
||||
public default int[] getBuckets() {
|
||||
return useData(Function.<int[]>identity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public default int getBucket(int index) {
|
||||
return useData(data -> data[index]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public default int transfer(int originalSrcBucketIndex, int originalDestBucketIndex, int originalAmount) {
|
||||
return useData(data -> {
|
||||
int srcBucketIndex = originalSrcBucketIndex;
|
||||
int destBucketIndex = originalDestBucketIndex;
|
||||
int amount = originalAmount;
|
||||
if (amount == 0) {
|
||||
return 0;
|
||||
}
|
||||
// Negative transfers will happen in the opposite direction
|
||||
if (amount < 0) {
|
||||
int tempIndex = srcBucketIndex;
|
||||
srcBucketIndex = destBucketIndex;
|
||||
destBucketIndex = tempIndex;
|
||||
amount = -amount;
|
||||
}
|
||||
if (amount > data[srcBucketIndex]) {
|
||||
amount = data[srcBucketIndex];
|
||||
}
|
||||
if (amount <= 0) {
|
||||
return 0;
|
||||
}
|
||||
data[srcBucketIndex] -= amount;
|
||||
data[destBucketIndex] += amount;
|
||||
return amount;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static final int NUM_BUCKETS = 10;
|
||||
private static final int PRINT_DELAY = 3_000;
|
||||
|
||||
private static int getTotal(int[] values) {
|
||||
return Arrays.stream(values)
|
||||
.parallel()
|
||||
.sum()
|
||||
;
|
||||
}
|
||||
|
||||
private static void equalizeBuckets(Buckets buckets) {
|
||||
Random r = new Random();
|
||||
while (true) {
|
||||
int srcBucketIndex = r.nextInt($.NUM_BUCKETS);
|
||||
int destBucketIndex = r.nextInt($.NUM_BUCKETS);
|
||||
Stream.of(srcBucketIndex, destBucketIndex)
|
||||
.map(buckets::getBucket)
|
||||
.reduce((srcBucketAmount, destBucketAmount) ->
|
||||
srcBucketAmount - destBucketAmount
|
||||
)
|
||||
.map(amount -> amount >> 1)
|
||||
.filter(amount -> amount != 0)
|
||||
.ifPresent(amount ->
|
||||
buckets.transfer(srcBucketIndex, destBucketIndex, amount)
|
||||
)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
private static void randomizeBuckets (Buckets buckets) {
|
||||
Random r = new Random();
|
||||
while (true) {
|
||||
int srcBucketIndex = r.nextInt($.NUM_BUCKETS);
|
||||
int destBucketIndex = r.nextInt($.NUM_BUCKETS);
|
||||
Stream.of(srcBucketIndex, destBucketIndex)
|
||||
.map(buckets::getBucket)
|
||||
.reduce((srcBucketAmount, destBucketAmount) ->
|
||||
r.nextInt(srcBucketAmount + destBucketAmount + 1) - destBucketAmount
|
||||
)
|
||||
.filter(amount -> amount != 0)
|
||||
.ifPresent(amount ->
|
||||
buckets.transfer(srcBucketIndex, destBucketIndex, amount)
|
||||
)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
private static Runnable run(Runnable runnable) {
|
||||
return runnable;
|
||||
}
|
||||
|
||||
private static void processBuckets(Buckets buckets) {
|
||||
Stream.<Consumer<Buckets>>of(
|
||||
$::equalizeBuckets,
|
||||
$::randomizeBuckets
|
||||
)
|
||||
.parallel()
|
||||
.map(consumer -> run(() -> consumer.accept(buckets)))
|
||||
.map(Thread::new)
|
||||
.forEach(Thread::start)
|
||||
;
|
||||
}
|
||||
|
||||
private static void displayBuckets(Buckets buckets) {
|
||||
while (true) {
|
||||
long nextPrintTime = System.currentTimeMillis() + PRINT_DELAY;
|
||||
long curTime;
|
||||
while ((curTime = System.currentTimeMillis()) < nextPrintTime) {
|
||||
try {
|
||||
Thread.sleep(nextPrintTime - curTime);
|
||||
}
|
||||
catch (InterruptedException e) {}
|
||||
}
|
||||
Stream.of(buckets)
|
||||
.parallel()
|
||||
.map(Buckets::getBuckets)
|
||||
.map(values -> "Current values: " + getTotal(values) + " " + Arrays.toString(values))
|
||||
.forEach(System.out::println)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
106
Task/Atomic-updates/Java/atomic-updates.java
Normal file
106
Task/Atomic-updates/Java/atomic-updates.java
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import java.util.Arrays;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class AtomicUpdates {
|
||||
|
||||
private static final int NUM_BUCKETS = 10;
|
||||
|
||||
public static class Buckets {
|
||||
private final int[] data;
|
||||
|
||||
public Buckets(int[] data) {
|
||||
this.data = data.clone();
|
||||
}
|
||||
|
||||
public int getBucket(int index) {
|
||||
synchronized (data) {
|
||||
return data[index];
|
||||
}
|
||||
}
|
||||
|
||||
public int transfer(int srcIndex, int dstIndex, int amount) {
|
||||
if (amount < 0)
|
||||
throw new IllegalArgumentException("negative amount: " + amount);
|
||||
if (amount == 0)
|
||||
return 0;
|
||||
|
||||
synchronized (data) {
|
||||
if (data[srcIndex] - amount < 0)
|
||||
amount = data[srcIndex];
|
||||
if (data[dstIndex] + amount < 0)
|
||||
amount = Integer.MAX_VALUE - data[dstIndex];
|
||||
if (amount < 0)
|
||||
throw new IllegalStateException();
|
||||
data[srcIndex] -= amount;
|
||||
data[dstIndex] += amount;
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getBuckets() {
|
||||
synchronized (data) {
|
||||
return data.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static long getTotal(int[] values) {
|
||||
long total = 0;
|
||||
for (int value : values) {
|
||||
total += value;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
|
||||
int[] values = new int[NUM_BUCKETS];
|
||||
for (int i = 0; i < values.length; i++)
|
||||
values[i] = rnd.nextInt() & Integer.MAX_VALUE;
|
||||
System.out.println("Initial Array: " + getTotal(values) + " " + Arrays.toString(values));
|
||||
|
||||
Buckets buckets = new Buckets(values);
|
||||
new Thread(() -> equalize(buckets), "equalizer").start();
|
||||
new Thread(() -> transferRandomAmount(buckets), "transferrer").start();
|
||||
new Thread(() -> print(buckets), "printer").start();
|
||||
}
|
||||
|
||||
private static void transferRandomAmount(Buckets buckets) {
|
||||
ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
while (true) {
|
||||
int srcIndex = rnd.nextInt(NUM_BUCKETS);
|
||||
int dstIndex = rnd.nextInt(NUM_BUCKETS);
|
||||
int amount = rnd.nextInt() & Integer.MAX_VALUE;
|
||||
buckets.transfer(srcIndex, dstIndex, amount);
|
||||
}
|
||||
}
|
||||
|
||||
private static void equalize(Buckets buckets) {
|
||||
ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
while (true) {
|
||||
int srcIndex = rnd.nextInt(NUM_BUCKETS);
|
||||
int dstIndex = rnd.nextInt(NUM_BUCKETS);
|
||||
int amount = (buckets.getBucket(srcIndex) - buckets.getBucket(dstIndex)) / 2;
|
||||
if (amount >= 0)
|
||||
buckets.transfer(srcIndex, dstIndex, amount);
|
||||
}
|
||||
}
|
||||
|
||||
private static void print(Buckets buckets) {
|
||||
while (true) {
|
||||
long nextPrintTime = System.currentTimeMillis() + 3000;
|
||||
long now;
|
||||
while ((now = System.currentTimeMillis()) < nextPrintTime) {
|
||||
try {
|
||||
Thread.sleep(nextPrintTime - now);
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int[] bucketValues = buckets.getBuckets();
|
||||
System.out.println("Current values: " + getTotal(bucketValues) + " " + Arrays.toString(bucketValues));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue