-
Notifications
You must be signed in to change notification settings - Fork 0
Java02. ДЗ 01, Старкова Анастасия, подгруппа 2 #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> | ||
| <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false"> | ||
| <output url="file://$MODULE_DIR$/target/classes" /> | ||
| <output-test url="file://$MODULE_DIR$/target/test-classes" /> | ||
| <content url="file://$MODULE_DIR$"> | ||
| <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> | ||
| <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> | ||
| <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> | ||
| <excludeFolder url="file://$MODULE_DIR$/target" /> | ||
| </content> | ||
| <orderEntry type="inheritedJdk" /> | ||
| <orderEntry type="sourceFolder" forTests="false" /> | ||
| <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" /> | ||
| <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" /> | ||
| <orderEntry type="library" name="Maven: org.hamcrest:hamcrest-all:1.3" level="project" /> | ||
| <orderEntry type="library" name="Maven: junit-addons:junit-addons:1.4" level="project" /> | ||
| <orderEntry type="library" name="Maven: xerces:xercesImpl:2.6.2" level="project" /> | ||
| <orderEntry type="library" name="Maven: xerces:xmlParserAPIs:2.6.2" level="project" /> | ||
| </component> | ||
| </module> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
|
|
||
| <groupId>ru.spbau.mit</groupId> | ||
| <artifactId>assignments</artifactId> | ||
| <version>1.0-SNAPSHOT</version> | ||
| <packaging>jar</packaging> | ||
|
|
||
| <name>assignments</name> | ||
| <url>http://maven.apache.org</url> | ||
|
|
||
| <properties> | ||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| </properties> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>junit</groupId> | ||
| <artifactId>junit</artifactId> | ||
| <version>4.12</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.hamcrest</groupId> | ||
| <artifactId>hamcrest-all</artifactId> | ||
| <version>1.3</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>junit-addons</groupId> | ||
| <artifactId>junit-addons</artifactId> | ||
| <version>1.4</version> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| <build> | ||
| <plugins> | ||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-compiler-plugin</artifactId> | ||
| <version>3.3</version> | ||
| <configuration> | ||
| <source>1.7</source> | ||
| <target>1.7</target> | ||
| <compilerArgs> | ||
| <arg>-Xlint:all</arg> | ||
| </compilerArgs> | ||
| </configuration> | ||
| </plugin> | ||
| <plugin> | ||
| <groupId>org.jacoco</groupId> | ||
| <artifactId>jacoco-maven-plugin</artifactId> | ||
| <version>0.7.5.201505241946</version> | ||
| <executions> | ||
| <execution> | ||
| <id>default-prepare-agent</id> | ||
| <goals> | ||
| <goal>prepare-agent</goal> | ||
| </goals> | ||
| </execution> | ||
| <execution> | ||
| <id>deafult-report</id> | ||
| <phase>test</phase> | ||
| <goals> | ||
| <goal>report</goal> | ||
| </goals> | ||
| </execution> | ||
| <execution> | ||
| <id>deafult-check</id> | ||
| <goals> | ||
| <goal>check</goal> | ||
| </goals> | ||
| </execution> | ||
| </executions> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
| </project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package ru.spbau.mit; | ||
|
|
||
| import java.util.function.Supplier; | ||
|
|
||
| public interface FactoryFromSupplier { | ||
| <T> Lazy<T> createLazy(Supplier<T> supplier); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| package ru.spbau.mit; | ||
|
|
||
| public interface Lazy<T> { | ||
| T get(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| package ru.spbau.mit; | ||
|
|
||
| import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; | ||
| import java.util.function.Supplier; | ||
|
|
||
| public class LazyFactory<T> { | ||
| public static <T> Lazy<T> createLazyOneThread(final Supplier<T> supplier) { | ||
| return new Lazy<T>() { | ||
| private boolean isCalled = false; | ||
| private T result; | ||
|
|
||
| public T get() { | ||
| if (!isCalled) { | ||
| result = supplier.get(); | ||
| isCalled = true; | ||
| } | ||
| return result; | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| public static <T> Lazy<T> createLazyMultiThread(final Supplier<T> supplier) { | ||
| return new Lazy<T>() { | ||
| 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<T> implements Lazy<T> { | ||
| private volatile T result; | ||
| private volatile Supplier<T> supplier; | ||
| private static final AtomicReferenceFieldUpdater<LockFreeLazy, Object> updater = | ||
| AtomicReferenceFieldUpdater.newUpdater(LockFreeLazy.class, Object.class, "result"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. имена констант пишутся капсом |
||
|
|
||
| public LockFreeLazy(Supplier<T> supp) { | ||
| supplier = supp; | ||
| } | ||
|
|
||
|
|
||
| public T get() { | ||
| Supplier<T> supp = supplier; | ||
| if (supp != null) { | ||
| if (updater.compareAndSet(this, null, supp.get())) { | ||
| supplier = null; | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| } | ||
|
|
||
| public static <T> Lazy<T> createLazyMultiThreadLockFree(Supplier<T> supplier) { | ||
| return new LockFreeLazy<T>(supplier); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<String> nullSupplier = new Supplier<String>() { | ||
| private boolean isCalled = false; | ||
|
|
||
| @Override | ||
| public String get() { | ||
| assertFalse(isCalled); | ||
| isCalled = true; | ||
| return null; | ||
| } | ||
| }; | ||
|
|
||
| private final Supplier<String> supplier = new Supplier<String>() { | ||
| private boolean isCalled = false; | ||
|
|
||
| @Override | ||
| public String get() { | ||
| assertFalse(isCalled); | ||
| isCalled = true; | ||
| return "I've done!"; | ||
| } | ||
| }; | ||
|
|
||
| //Special functions for tests | ||
|
|
||
| private void checkForNullTests(Lazy<String> lazy) { | ||
| assertNull(lazy.get()); | ||
| assertNull(lazy.get()); | ||
| } | ||
|
|
||
| private void checkForEqualTests(Lazy<String> lazy) { | ||
| String firstGet = lazy.get(); | ||
| String secondGet = lazy.get(); | ||
| assertEquals(firstGet, secondGet); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. лучше assertSame, который проверит не эквивалентность, а на == |
||
| assertEquals(firstGet, "I've done!"); | ||
| } | ||
|
|
||
| private Supplier<Integer> createMultiThreadSupplier(final Random random) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не используется (IDEA подсвечивает), надо удалить |
||
| return new Supplier<Integer>() { | ||
| @Override | ||
| public Integer get() { | ||
| return random.nextInt(500); | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| private static class SupplCounter implements Supplier<Object> { | ||
| private AtomicInteger cnt = new AtomicInteger(0); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. final |
||
| private Object result; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. final |
||
|
|
||
| SupplCounter(Object result) { | ||
| this.result = result; | ||
| } | ||
|
|
||
| @Override | ||
| public Object get() { | ||
| Thread.yield(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. зачем? |
||
| cnt.incrementAndGet(); | ||
| return result; | ||
| } | ||
|
|
||
| public Integer getCount() { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. int |
||
| return cnt.get(); | ||
| } | ||
| } | ||
|
|
||
| private void checkForMultiThread(FactoryFromSupplier factory, boolean isSupplierCalledOnce, | ||
| Object returnValue) { | ||
| SupplCounter supplier = new SupplCounter(returnValue); | ||
| Lazy<Object> lazy = factory.createLazy(supplier); | ||
|
|
||
| List<Thread> tasks = new ArrayList<>(); | ||
| List<Object> results = Collections.synchronizedList(new ArrayList<>()); | ||
| CyclicBarrier barrier = new CyclicBarrier(NUMBER_OF_THREADS); | ||
|
|
||
| for (int i = 0; i < NUMBER_OF_THREADS; i++) { | ||
| Thread task = new Thread(() -> { | ||
| try { | ||
| barrier.await(); | ||
| } catch (Exception e) { | ||
| e.printStackTrace(); | ||
| } | ||
| results.add(lazy.get()); | ||
| }); | ||
| tasks.add(task); | ||
| task.start(); | ||
| } | ||
|
|
||
| for (Thread task : tasks) { | ||
| try { | ||
| task.join(); | ||
| } catch (InterruptedException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. С пятью потоками и простеньким run довольно трудно сделать имитацию гонки данных - лучше запустить потоки, дождаться, чтобы они дошли до определенного места с помощью барьера, а потом всем продолжить исполнение. Это будет гораздо ближе к гонке данных. |
||
|
|
||
| assertEquals(NUMBER_OF_THREADS, results.size()); | ||
|
|
||
| for (Object result : results) { | ||
| assertTrue(returnValue == result); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assertSame |
||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Вместо этого лучше пробежаться по threads и на каждом потоке вызвать join. |
||
|
|
||
| assertTrue(supplier.getCount() > 0); | ||
| if (isSupplierCalledOnce) { | ||
| assertTrue(1 == supplier.getCount()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assertEquals |
||
| } | ||
| } | ||
|
|
||
| //Tests for one thread | ||
| @Test | ||
| public void nullTestLazyForOneThread() { | ||
| Lazy<String> lazy = LazyFactory.createLazyOneThread(nullSupplier); | ||
| checkForNullTests(lazy); | ||
| } | ||
|
|
||
| @Test | ||
| public void equalsTestLazyForOneThread() { | ||
| Lazy<String> lazy = LazyFactory.createLazyOneThread(supplier); | ||
| checkForEqualTests(lazy); | ||
| } | ||
|
|
||
| private static class classWrapper<T> { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. классы именуются с большой буквы |
||
| public volatile T content; | ||
|
|
||
| public classWrapper(T content) { | ||
| this.content = content; | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| public void lazinessTestLazyForOneThread() { | ||
| classWrapper<Boolean> isAsked = new classWrapper<>(false); | ||
|
|
||
| Lazy<String> lazy = LazyFactory.createLazyOneThread(() -> { | ||
| assertTrue(isAsked.content); | ||
| return "It's OK!"; | ||
| }); | ||
|
|
||
| isAsked.content = true; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ленивость проверяется только для однопоточного lazy. Лучше эту проверку засунуть в методы checkForNullTests, checkForEqualTests и checkForEqualTests |
||
|
|
||
| //MultiThread tests | ||
|
|
||
| @Test | ||
| public void nullTestLazyMultiThread() { | ||
| Lazy<String> lazy = LazyFactory.createLazyMultiThread(nullSupplier); | ||
| checkForNullTests(lazy); | ||
| } | ||
|
|
||
| @Test | ||
| public void equalsTestLazyMultiThread() { | ||
| Lazy<String> lazy = LazyFactory.createLazyMultiThread(supplier); | ||
| checkForEqualTests(lazy); | ||
| } | ||
|
|
||
| @Test | ||
| public void dataRaceTestLazyMultiThread() { | ||
| checkForMultiThread(LazyFactory::createLazyMultiThread, true, new Object()); | ||
| } | ||
|
|
||
| //MultiThread lock-free tests | ||
|
|
||
| @Test | ||
| public void nullTestLazyMultiThreadLockFree() { | ||
| Lazy<String> lazy = LazyFactory.createLazyMultiThreadLockFree(nullSupplier); | ||
| checkForNullTests(lazy); | ||
| } | ||
|
|
||
| @Test | ||
| public void equalsTestLazyMultiThreadLockFree() { | ||
| Lazy<String> myLazy = LazyFactory.createLazyMultiThreadLockFree(supplier); | ||
| checkForEqualTests(myLazy); | ||
| } | ||
|
|
||
| @Test | ||
| public void dataRaceTestLazyMultiThreadLockFree() { | ||
| checkForMultiThread(LazyFactory::createLazyMultiThreadLockFree, false, new Object()); | ||
| } | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нет теста, что вычисление только по требованию |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Используется только в тестах, значит только там и должен жить )