From dd4cf58d3d3e3484a178fe2b6a3c4300165207c9 Mon Sep 17 00:00:00 2001 From: alyokhina-olya Date: Fri, 9 Mar 2018 04:35:25 +0300 Subject: [PATCH 1/4] first commit --- .travis.yml | 7 + 01.Pool/pom.xml | 31 ++++ .../alyokhina/LightExecutionException.java | 7 + .../ru/spbau/mit/alyokhina/LightFuture.java | 22 +++ .../java/ru/spbau/mit/alyokhina/Pool.java | 165 ++++++++++++++++++ .../java/ru/spbau/mit/alyokhina/PoolTest.java | 100 +++++++++++ buildscript.sh | 9 + 7 files changed, 341 insertions(+) create mode 100644 .travis.yml create mode 100644 01.Pool/pom.xml create mode 100644 01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightExecutionException.java create mode 100644 01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java create mode 100644 01.Pool/src/main/java/ru/spbau/mit/alyokhina/Pool.java create mode 100644 01.Pool/src/test/java/ru/spbau/mit/alyokhina/PoolTest.java create mode 100755 buildscript.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6b8dde0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: java +jdk: + - oraclejdk8 +os: + - linux +script: + - chmod +x buildscript.sh && ./buildscript.sh diff --git a/01.Pool/pom.xml b/01.Pool/pom.xml new file mode 100644 index 0000000..a0377c5 --- /dev/null +++ b/01.Pool/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + 01 + Pool + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + junit + junit + 4.12 + + + + + \ No newline at end of file diff --git a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightExecutionException.java b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightExecutionException.java new file mode 100644 index 0000000..16dabef --- /dev/null +++ b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightExecutionException.java @@ -0,0 +1,7 @@ +package ru.spbau.mit.alyokhina; +/** if in calculating supplier of the LightFuture we caught an exception, we throw LightExecutionException */ +public class LightExecutionException extends Exception { + public LightExecutionException(String msg) { + super(msg); + } +} diff --git a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java new file mode 100644 index 0000000..6759a21 --- /dev/null +++ b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java @@ -0,0 +1,22 @@ +package ru.spbau.mit.alyokhina; + +import java.util.function.Function; + +/** Interface for tasks accepted for execution */ +public interface LightFuture { + /** if task was calculated then return true, else - false */ + boolean isReady(); + + /** + * Calculate supplier + * @return the value obtained + * @throws LightExecutionException if in calculating supplier of the LightFuture we caught an exception + */ + T get() throws LightExecutionException; + + /** + * Accepts an object of type Function that can be applied to the result of this task T and returns a new task E accepted for execution + * @return new task type of E + */ + LightFuture thenApply(Function function); +} diff --git a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/Pool.java b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/Pool.java new file mode 100644 index 0000000..e623482 --- /dev/null +++ b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/Pool.java @@ -0,0 +1,165 @@ +package ru.spbau.mit.alyokhina; + +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * Task pool with a fixed number of threads + */ +public class Pool { + /** + * All created threads + */ + private Thread threads[]; + + /** + * Accepted tasks + */ + private final Queue tasks = new ArrayDeque<>(); + + /** + * Constructor + * + * @param n number of threads + */ + public Pool(int n) { + threads = new Thread[n]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread(() -> { + LightFutureImpl cur; + try { + while (!Thread.interrupted()) { + synchronized (tasks) { + while (tasks.isEmpty()) { + tasks.wait(); + } + cur = tasks.poll(); + } + cur.calculate(); + } + } + catch (InterruptedException e) { + } + } + ); + threads[i].start(); + } + } + + /** + * Shutting down all threads + */ + public void shutdown() { + for (Thread thread : threads) { + thread.interrupt(); + } + } + + /** Return all threads */ + public Thread[] getThreads() { + return threads; + } + + /** + * Add new task and notify threads that are waiting for a new task + */ + public LightFuture add(Supplier supplier) { + LightFutureImpl newTask = new LightFutureImpl<>(supplier); + synchronized (tasks) { + tasks.add(newTask); + tasks.notify(); + } + return newTask; + } + + /** + * Class for task implements LightFuture + */ + private class LightFutureImpl implements LightFuture { + /** + * value was calculated + */ + private boolean ready = false; + + /** + * Error in calculating the supplier + */ + private LightExecutionException exception; + private Supplier supplier; + /** + * the value that was received when calculating the supplier + */ + private T ans = null; + + /** + * Constructor + * + * @param supplier for calculating value + */ + public LightFutureImpl(Supplier supplier) { + this.supplier = supplier; + } + + /** + * Value was calculated + * + * @return true if value was calculated, false - else + */ + @Override + public boolean isReady() { + return ready; + } + + /** + * Calculate task + */ + private synchronized void calculate() { + if (!ready) { + try { + ans = supplier.get(); + } catch (Exception e) { + exception = new LightExecutionException(e.getMessage()); + } + ready = true; + notifyAll(); + } + } + + /** + * expect calculation if not calculated yet + * + * @return result which was calculated + * @throws LightExecutionException if in calculating supplier of the LightFuture we caught an exception + */ + public synchronized T get() throws LightExecutionException { + while (!ready) { + try { + wait(); + } catch (InterruptedException e) { + throw new LightExecutionException("Interrupted"); + } + } + if (exception != null) { + throw exception; + } + return ans; + } + + /** + * Accepts an object of type Function that can be applied to the result of this task T and returns a new task E accepted for execution + * + * @return new task type of E + */ + public LightFuture thenApply(Function function) { + return add(() -> { + try { + return function.apply(get()); + } catch (LightExecutionException e) { + throw new RuntimeException(e.getMessage(), e.getCause()); + } + }); + } + } +} \ No newline at end of file diff --git a/01.Pool/src/test/java/ru/spbau/mit/alyokhina/PoolTest.java b/01.Pool/src/test/java/ru/spbau/mit/alyokhina/PoolTest.java new file mode 100644 index 0000000..ca54707 --- /dev/null +++ b/01.Pool/src/test/java/ru/spbau/mit/alyokhina/PoolTest.java @@ -0,0 +1,100 @@ +package ru.spbau.mit.alyokhina; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class PoolTest { + @Test + public void testConstructor() { + Pool threadPools = new Pool(5); + for (int i = 0; i < 5; i++) { + final int j = i; + threadPools.add(() -> j); + } + } + + /** + * @throws LightExecutionException if in calculating supplier of the LightFuture we caught an exception + */ + @Test + public void testWithOneThread() throws LightExecutionException { + Pool threadPools = new Pool(1); + LightFuture task = threadPools.add(() -> 1408); + assertEquals((Integer) 1408, task.get()); + } + + + /** + * @throws LightExecutionException if in calculating supplier of the LightFuture we caught an exception + */ + @Test + public void testAdd() throws LightExecutionException { + Pool threadPools = new Pool(15); + LightFuture tasks[] = new LightFuture[20]; + for (int i = 0; i < 20; i++) { + final int j = i; + tasks[i] = threadPools.add(() -> j); + } + + for (int i = 0; i < 20; i++) { + assertEquals((Integer) i, tasks[i].get()); + } + + } + + @Test(expected = LightExecutionException.class) + public void testLightExecutionException() throws LightExecutionException { + Pool threadPools = new Pool(15); + LightFuture tasks[] = new LightFuture[5]; + for (int i = 0; i < 5; i++) { + tasks[i] = threadPools.add(() -> { + throw new RuntimeException(""); + }); + } + for (int i = 0; i < 5; i++) { + tasks[i].get(); + } + } + + @Test + public void testShutdown() { + Pool threadPools = new Pool(15); + LightFuture tasks[] = new LightFuture[20]; + for (int i = 0; i < 20; i++) { + final int j = i; + tasks[i] = threadPools.add(() -> j); + } + threadPools.shutdown(); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + System.out.println(e.getMessage()); + } + Thread[] threads = threadPools.getThreads(); + for (int i = 0; i < threads.length; i++) { + assertEquals(false, threads[i].isAlive()); + } + } + + /** + * @throws LightExecutionException if in calculating supplier of the LightFuture we caught an exception + */ + @Test + public void tesThenApplyOnce() throws LightExecutionException { + Pool threadPools = new Pool(15); + LightFuture task = threadPools.add(() -> 5).thenApply(x -> x * 2); + assertEquals((Integer) 10, task.get()); + } + + /** + * @throws LightExecutionException if in calculating supplier of the LightFuture we caught an exception + */ + @Test + public void tesThenApply() throws LightExecutionException { + Pool threadPools = new Pool(15); + LightFuture task = threadPools.add(() -> 5).thenApply(x -> x * 2).thenApply(x -> x + 4); + assertEquals((Integer) 14, task.get()); + } + +} \ No newline at end of file diff --git a/buildscript.sh b/buildscript.sh new file mode 100755 index 0000000..1cc07e7 --- /dev/null +++ b/buildscript.sh @@ -0,0 +1,9 @@ +#!/bin/bash +files=$(find . -maxdepth 1 -type d | grep "./0.*") +for file in $files +do + cd $file + mvn test -B + cd ../ +done + From 3e78f251af7e478150e239e7a9c989aefd5d3e29 Mon Sep 17 00:00:00 2001 From: alyokhina-olya Date: Fri, 9 Mar 2018 04:52:46 +0300 Subject: [PATCH 2/4] commit for travis --- .../java/ru/spbau/mit/alyokhina/LightExecutionException.java | 1 + 1 file changed, 1 insertion(+) diff --git a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightExecutionException.java b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightExecutionException.java index 16dabef..745c303 100644 --- a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightExecutionException.java +++ b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightExecutionException.java @@ -1,4 +1,5 @@ package ru.spbau.mit.alyokhina; + /** if in calculating supplier of the LightFuture we caught an exception, we throw LightExecutionException */ public class LightExecutionException extends Exception { public LightExecutionException(String msg) { From 84e60342d9f39868cde7b25c477283628e622495 Mon Sep 17 00:00:00 2001 From: alyokhina-olya Date: Sat, 17 Mar 2018 13:02:20 +0300 Subject: [PATCH 3/4] fix generic parametr --- .../java/ru/spbau/mit/alyokhina/LightFuture.java | 2 +- .../src/main/java/ru/spbau/mit/alyokhina/Pool.java | 12 ++++++------ .../test/java/ru/spbau/mit/alyokhina/PoolTest.java | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java index 6759a21..1b58986 100644 --- a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java +++ b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java @@ -18,5 +18,5 @@ public interface LightFuture { * Accepts an object of type Function that can be applied to the result of this task T and returns a new task E accepted for execution * @return new task type of E */ - LightFuture thenApply(Function function); + LightFuture thenApply(Function function); } diff --git a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/Pool.java b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/Pool.java index e623482..fe008bb 100644 --- a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/Pool.java +++ b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/Pool.java @@ -8,7 +8,7 @@ /** * Task pool with a fixed number of threads */ -public class Pool { +public class Pool { /** * All created threads */ @@ -40,7 +40,7 @@ public Pool(int n) { cur.calculate(); } } - catch (InterruptedException e) { + catch (InterruptedException ignored) { } } ); @@ -65,8 +65,8 @@ public Thread[] getThreads() { /** * Add new task and notify threads that are waiting for a new task */ - public LightFuture add(Supplier supplier) { - LightFutureImpl newTask = new LightFutureImpl<>(supplier); + public LightFuture add(Supplier supplier) { + LightFutureImpl newTask = new LightFutureImpl(supplier); synchronized (tasks) { tasks.add(newTask); tasks.notify(); @@ -77,7 +77,7 @@ public LightFuture add(Supplier supplier) { /** * Class for task implements LightFuture */ - private class LightFutureImpl implements LightFuture { + private class LightFutureImpl implements LightFuture { /** * value was calculated */ @@ -152,7 +152,7 @@ public synchronized T get() throws LightExecutionException { * * @return new task type of E */ - public LightFuture thenApply(Function function) { + public LightFuture thenApply(Function function) { return add(() -> { try { return function.apply(get()); diff --git a/01.Pool/src/test/java/ru/spbau/mit/alyokhina/PoolTest.java b/01.Pool/src/test/java/ru/spbau/mit/alyokhina/PoolTest.java index ca54707..9a4884a 100644 --- a/01.Pool/src/test/java/ru/spbau/mit/alyokhina/PoolTest.java +++ b/01.Pool/src/test/java/ru/spbau/mit/alyokhina/PoolTest.java @@ -7,7 +7,7 @@ public class PoolTest { @Test public void testConstructor() { - Pool threadPools = new Pool(5); + Pool threadPools = new Pool<>(5); for (int i = 0; i < 5; i++) { final int j = i; threadPools.add(() -> j); @@ -19,7 +19,7 @@ public void testConstructor() { */ @Test public void testWithOneThread() throws LightExecutionException { - Pool threadPools = new Pool(1); + Pool threadPools = new Pool<>(1); LightFuture task = threadPools.add(() -> 1408); assertEquals((Integer) 1408, task.get()); } @@ -30,7 +30,7 @@ public void testWithOneThread() throws LightExecutionException { */ @Test public void testAdd() throws LightExecutionException { - Pool threadPools = new Pool(15); + Pool threadPools = new Pool<>(15); LightFuture tasks[] = new LightFuture[20]; for (int i = 0; i < 20; i++) { final int j = i; @@ -45,7 +45,7 @@ public void testAdd() throws LightExecutionException { @Test(expected = LightExecutionException.class) public void testLightExecutionException() throws LightExecutionException { - Pool threadPools = new Pool(15); + Pool threadPools = new Pool<>(15); LightFuture tasks[] = new LightFuture[5]; for (int i = 0; i < 5; i++) { tasks[i] = threadPools.add(() -> { @@ -59,7 +59,7 @@ public void testLightExecutionException() throws LightExecutionException { @Test public void testShutdown() { - Pool threadPools = new Pool(15); + Pool threadPools = new Pool<>(15); LightFuture tasks[] = new LightFuture[20]; for (int i = 0; i < 20; i++) { final int j = i; @@ -82,7 +82,7 @@ public void testShutdown() { */ @Test public void tesThenApplyOnce() throws LightExecutionException { - Pool threadPools = new Pool(15); + Pool threadPools = new Pool<>(15); LightFuture task = threadPools.add(() -> 5).thenApply(x -> x * 2); assertEquals((Integer) 10, task.get()); } @@ -92,7 +92,7 @@ public void tesThenApplyOnce() throws LightExecutionException { */ @Test public void tesThenApply() throws LightExecutionException { - Pool threadPools = new Pool(15); + Pool threadPools = new Pool<>(15); LightFuture task = threadPools.add(() -> 5).thenApply(x -> x * 2).thenApply(x -> x + 4); assertEquals((Integer) 14, task.get()); } From e1f7388cf44cf4d9603aa0325ccd576603c79524 Mon Sep 17 00:00:00 2001 From: alyokhina-olya Date: Sat, 17 Mar 2018 13:03:56 +0300 Subject: [PATCH 4/4] fix javadoc --- 01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java index 1b58986..6f53c17 100644 --- a/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java +++ b/01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java @@ -15,8 +15,8 @@ public interface LightFuture { T get() throws LightExecutionException; /** - * Accepts an object of type Function that can be applied to the result of this task T and returns a new task E accepted for execution - * @return new task type of E + * Accepts an object of type Function that can be applied to the result of this task T and returns a new task T accepted for execution + * @return new task type of T */ LightFuture thenApply(Function function); }