diff --git a/Java_4sem.iml b/Java_4sem.iml
new file mode 100644
index 0000000..22f739f
--- /dev/null
+++ b/Java_4sem.iml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..2319589
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,78 @@
+
+ 4.0.0
+
+ ru.spbau.mit
+ assignments
+ 1.0-SNAPSHOT
+ jar
+
+ assignments
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.hamcrest
+ hamcrest-all
+ 1.3
+
+
+ junit-addons
+ junit-addons
+ 1.4
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.3
+
+ 1.7
+ 1.7
+
+ -Xlint:all
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.7.5.201505241946
+
+
+ default-prepare-agent
+
+ prepare-agent
+
+
+
+ deafult-report
+ test
+
+ report
+
+
+
+ deafult-check
+
+ check
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/ru/spbau/mit/FactoryFromSupplier.java b/src/main/java/ru/spbau/mit/FactoryFromSupplier.java
new file mode 100644
index 0000000..a8a704a
--- /dev/null
+++ b/src/main/java/ru/spbau/mit/FactoryFromSupplier.java
@@ -0,0 +1,7 @@
+package ru.spbau.mit;
+
+import java.util.function.Supplier;
+
+public interface FactoryFromSupplier {
+ Lazy createLazy(Supplier supplier);
+}
diff --git a/src/main/java/ru/spbau/mit/Lazy.java b/src/main/java/ru/spbau/mit/Lazy.java
new file mode 100644
index 0000000..66428c4
--- /dev/null
+++ b/src/main/java/ru/spbau/mit/Lazy.java
@@ -0,0 +1,5 @@
+package ru.spbau.mit;
+
+public interface Lazy {
+ T get();
+}
\ No newline at end of file
diff --git a/src/main/java/ru/spbau/mit/LazyFactory.java b/src/main/java/ru/spbau/mit/LazyFactory.java
new file mode 100644
index 0000000..73a93cb
--- /dev/null
+++ b/src/main/java/ru/spbau/mit/LazyFactory.java
@@ -0,0 +1,66 @@
+package ru.spbau.mit;
+
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.util.function.Supplier;
+
+public class LazyFactory {
+ public static Lazy createLazyOneThread(final Supplier supplier) {
+ return new Lazy() {
+ private boolean isCalled = false;
+ private T result;
+
+ public T get() {
+ if (!isCalled) {
+ result = supplier.get();
+ isCalled = true;
+ }
+ return result;
+ }
+ };
+ }
+
+ public static Lazy createLazyMultiThread(final Supplier supplier) {
+ return new Lazy() {
+ private volatile boolean isCalled = false;
+ private volatile T result;
+
+ public T get() {
+ if (!isCalled) {
+ synchronized (this) {
+ if (!isCalled) {
+ result = supplier.get();
+ isCalled = true;
+ }
+ }
+ }
+ return result;
+ }
+ };
+ }
+
+ private static class LockFreeLazy implements Lazy {
+ private volatile T result;
+ private volatile Supplier supplier;
+ private static final AtomicReferenceFieldUpdater updater =
+ AtomicReferenceFieldUpdater.newUpdater(LockFreeLazy.class, Object.class, "result");
+
+ public LockFreeLazy(Supplier supp) {
+ supplier = supp;
+ }
+
+
+ public T get() {
+ Supplier supp = supplier;
+ if (supp != null) {
+ if (updater.compareAndSet(this, null, supp.get())) {
+ supplier = null;
+ }
+ }
+ return result;
+ }
+ }
+
+ public static Lazy createLazyMultiThreadLockFree(Supplier supplier) {
+ return new LockFreeLazy(supplier);
+ }
+}
diff --git a/src/test/java/ru/spbau/mit/LazyFactoryTest.java b/src/test/java/ru/spbau/mit/LazyFactoryTest.java
new file mode 100644
index 0000000..e4f76c9
--- /dev/null
+++ b/src/test/java/ru/spbau/mit/LazyFactoryTest.java
@@ -0,0 +1,195 @@
+package ru.spbau.mit;
+
+import org.junit.Test;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
+
+import static org.junit.Assert.*;
+
+public class LazyFactoryTest {
+
+ private static final int NUMBER_OF_THREADS = 50;
+
+ //Create suppliers
+
+ private final Supplier nullSupplier = new Supplier() {
+ private boolean isCalled = false;
+
+ @Override
+ public String get() {
+ assertFalse(isCalled);
+ isCalled = true;
+ return null;
+ }
+ };
+
+ private final Supplier supplier = new Supplier() {
+ private boolean isCalled = false;
+
+ @Override
+ public String get() {
+ assertFalse(isCalled);
+ isCalled = true;
+ return "I've done!";
+ }
+ };
+
+ //Special functions for tests
+
+ private void checkForNullTests(Lazy lazy) {
+ assertNull(lazy.get());
+ assertNull(lazy.get());
+ }
+
+ private void checkForEqualTests(Lazy lazy) {
+ String firstGet = lazy.get();
+ String secondGet = lazy.get();
+ assertEquals(firstGet, secondGet);
+ assertEquals(firstGet, "I've done!");
+ }
+
+ private Supplier createMultiThreadSupplier(final Random random) {
+ return new Supplier() {
+ @Override
+ public Integer get() {
+ return random.nextInt(500);
+ }
+ };
+ }
+
+ private static class SupplCounter implements Supplier