Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: java
jdk:
- oraclejdk8
os:
- linux
script:
- chmod +x buildscript.sh && ./buildscript.sh
31 changes: 31 additions & 0 deletions 01.Pool/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>01</groupId>
<artifactId>Pool</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
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);
}
}
22 changes: 22 additions & 0 deletions 01.Pool/src/main/java/ru/spbau/mit/alyokhina/LightFuture.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package ru.spbau.mit.alyokhina;

import java.util.function.Function;

/** Interface for tasks accepted for execution */
public interface LightFuture<T> {
/** 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 T accepted for execution
* @return new task type of T
*/
LightFuture<T> thenApply(Function<T, T> function);
}
165 changes: 165 additions & 0 deletions 01.Pool/src/main/java/ru/spbau/mit/alyokhina/Pool.java
Original file line number Diff line number Diff line change
@@ -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<T> {
/**
* All created threads
*/
private Thread threads[];

/**
* Accepted tasks
*/
private final Queue<LightFutureImpl> 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 ignored) {
}
}
);
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<T> add(Supplier<T> 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<T> {
/**
* value was calculated
*/
private boolean ready = false;

/**
* Error in calculating the supplier
*/
private LightExecutionException exception;
private Supplier<T> supplier;
/**
* the value that was received when calculating the supplier
*/
private T ans = null;

/**
* Constructor
*
* @param supplier for calculating value
*/
public LightFutureImpl(Supplier<T> 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<T> thenApply(Function<T, T> function) {
return add(() -> {
try {
return function.apply(get());
} catch (LightExecutionException e) {
throw new RuntimeException(e.getMessage(), e.getCause());
}
});
}
}
}
100 changes: 100 additions & 0 deletions 01.Pool/src/test/java/ru/spbau/mit/alyokhina/PoolTest.java
Original file line number Diff line number Diff line change
@@ -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<Integer> 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<Integer> threadPools = new Pool<>(1);
LightFuture<Integer> 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<Integer> threadPools = new Pool<>(15);
LightFuture<Integer> 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<Integer> threadPools = new Pool<>(15);
LightFuture<Integer> 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<Integer> threadPools = new Pool<>(15);
LightFuture<Integer> 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<Integer> threadPools = new Pool<>(15);
LightFuture<Integer> 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<Integer> threadPools = new Pool<>(15);
LightFuture<Integer> task = threadPools.add(() -> 5).thenApply(x -> x * 2).thenApply(x -> x + 4);
assertEquals((Integer) 14, task.get());
}

}
9 changes: 9 additions & 0 deletions buildscript.sh
Original file line number Diff line number Diff line change
@@ -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