Skip to content

Instantly share code, notes, and snippets.

@kundzi
Last active August 29, 2015 14:27
Show Gist options
  • Select an option

  • Save kundzi/7c72d478fc9aaf1a9dfd to your computer and use it in GitHub Desktop.

Select an option

Save kundzi/7c72d478fc9aaf1a9dfd to your computer and use it in GitHub Desktop.
// Here is the test lives
package com.company;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.function.Consumer;
public class Main {
static class SetterThread<T> extends Thread {
final SynchProperty<T> target;
final T value;
final long timeout;
SetterThread(SynchProperty<T> target, T value, long timeout) {
this.target = target;
this.value = value;
this.timeout = timeout;
}
@Override
public void run() {
try {
Thread.sleep(timeout);
target.set(value);
System.out.printf("Set to: %s <-> %s\n", value, target.get());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static <T> SetterThread<T> create(SynchProperty<T> target, T value, long timeout) {
return new SetterThread<T>(target, value, timeout);
}
}
enum TestEnum {
A, B, C, D, E
}
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
runTest();
}
}
private static void runTest() {
final SynchProperty<TestEnum> property = new SynchProperty<TestEnum>();
SetterThread.create(property, TestEnum.A, 100).start();
SetterThread.create(property, TestEnum.B, 150).start();
SetterThread.create(property, TestEnum.C, 200).start();
SetterThread.create(property, TestEnum.D, 250).start();
SetterThread.create(property, TestEnum.E, 300).start();
SetterThread.create(property, null, 350).start();
final ArrayList<TestEnum> valueToWait = Lists.newArrayList(TestEnum.values());
valueToWait.add(null); // last value
valueToWait.stream().forEach(new Consumer<TestEnum>() {
@Override
public void accept(TestEnum expected) {
System.out.printf("Waiting for: %s, current: %s\n", expected, property.get());
Preconditions.checkState(property.waitForValue(expected));
System.out.printf("Received value: %s, current: %s\n", expected, property.get());
}
});
SetterThread.create(property, TestEnum.A, 100).start();
SetterThread.create(property, TestEnum.B, 150).start();
SetterThread.create(property, TestEnum.C, 200).start();
SetterThread.create(property, TestEnum.D, 250).start();
SetterThread.create(property, TestEnum.E, 300).start();
SetterThread.create(property, null, 350).start();
valueToWait.stream().forEach(new Consumer<TestEnum>() {
@Override
public void accept(TestEnum expected) {
final long timeout = 400;
System.out.printf("Waiting with timeout[%d] for: %s, current: %s\n", timeout, expected, property.get());
Preconditions.checkState(property.waitForValue(expected, timeout));
System.out.printf("Received value: %s, current: %s\n", expected, property.get());
}
});
SetterThread.create(property, TestEnum.A, 100).start();
Preconditions.checkState(!property.waitForValue(TestEnum.A, 10));
SetterThread.create(property, TestEnum.B, 100).start();
Preconditions.checkState(!property.waitForValue(TestEnum.B, 1));
try {
property.waitForValue(TestEnum.C, 0);
Preconditions.checkState(false);
} catch (Exception expected) {
System.out.printf("Cant use not positive timeout. Bla\n");
}
}
}
package com.company;
import com.google.common.base.Preconditions;
import java.util.Objects;
/**
* Created by 7times6 on 20/08/15.
*/
public class SynchProperty<T> {
private final Object mutex = new Object();
private T value;
public void set(T value) {
synchronized (mutex) {
this.value = value;
mutex.notifyAll();
}
}
public T get() {
synchronized (mutex) {
return value;
}
}
public boolean waitForValue(T expected) {
synchronized (mutex) {
if (Objects.equals(value, expected)) {
return true;
}
while (value != expected) {
try {
mutex.wait();
} catch (InterruptedException e) {
return false;
}
}
return true;
}
}
public boolean waitForValue(T expected, long timeout) {
Preconditions.checkArgument(timeout > 0);
synchronized (mutex) {
final long startTime = System.currentTimeMillis();
final long endTime = startTime + timeout;
while (endTime >= System.currentTimeMillis()) {
if (Objects.equals(value, expected)) {
return true;
}
final long timeToWait = endTime - System.currentTimeMillis();
try {
if (timeToWait > 0) {
mutex.wait();
}
} catch (InterruptedException e) {
return false;
}
}
return false;
}
}
@Override
public String toString() {
return "SyncProperty:" + String.valueOf(value) + "]";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment