-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3ea530a
commit 37b2bc9
Showing
12 changed files
with
406 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package edu.hw7.task1; | ||
|
||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
public class MultiCounter { | ||
|
||
private final AtomicInteger counter; | ||
|
||
public MultiCounter() { | ||
counter = new AtomicInteger(0); | ||
} | ||
|
||
public void increment() { | ||
counter.incrementAndGet(); | ||
} | ||
|
||
public int get() { | ||
return counter.get(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package edu.hw7.task2; | ||
|
||
import java.util.stream.IntStream; | ||
|
||
public final class ParallelFactorial { | ||
|
||
private ParallelFactorial() { | ||
} | ||
|
||
public static int computeFactorial(int n) { | ||
return IntStream.rangeClosed(1, n) | ||
.parallel() | ||
.reduce((i1, i2) -> i1 * i2) | ||
.orElseThrow(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package edu.hw7.task3; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import lombok.SneakyThrows; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public class AbstractPersonDatabase implements PersonDatabase { | ||
|
||
private final Map<Integer, Person> cachedIds = new HashMap<>(); | ||
private final Map<String, List<Person>> cachedNames = new HashMap<>(); | ||
private final Map<String, List<Person>> cachedAddresses = new HashMap<>(); | ||
private final Map<String, List<Person>> cachedPhones = new HashMap<>(); | ||
|
||
@SneakyThrows | ||
@Override | ||
public void add(Person person) { | ||
cachedIds.put(person.id(), person); | ||
cachedNames.computeIfAbsent(person.name(), name -> new ArrayList<>()).add(person); | ||
cachedAddresses.computeIfAbsent(person.address(), name -> new ArrayList<>()).add(person); | ||
cachedPhones.computeIfAbsent(person.phoneNumber(), name -> new ArrayList<>()).add(person); | ||
} | ||
|
||
@Override | ||
public void delete(int id) { | ||
Person removed = cachedIds.remove(id); | ||
if (removed == null) { | ||
return; | ||
} | ||
cachedNames.remove(removed.name()); | ||
cachedAddresses.remove(removed.address()); | ||
cachedPhones.remove(removed.phoneNumber()); | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public List<Person> findByName(String name) { | ||
if (!cachedNames.containsKey(name)) { | ||
return null; | ||
} | ||
return cachedNames.get(name).stream().toList(); | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public List<Person> findByAddress(String address) { | ||
if (!cachedAddresses.containsKey(address)) { | ||
return null; | ||
} | ||
return cachedAddresses.get(address).stream().toList(); | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public List<Person> findByPhone(String phone) { | ||
if (!cachedPhones.containsKey(phone)) { | ||
return null; | ||
} | ||
return cachedPhones.get(phone).stream().toList(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package edu.hw7.task3; | ||
|
||
import java.util.List; | ||
import lombok.SneakyThrows; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public class CachingPersonDatabase extends AbstractPersonDatabase { | ||
|
||
@SneakyThrows | ||
@Override | ||
public synchronized void add(Person person) { | ||
super.add(person); | ||
} | ||
|
||
@Override | ||
public synchronized void delete(int id) { | ||
super.delete(id); | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public synchronized List<Person> findByName(String name) { | ||
return super.findByName(name); | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public synchronized List<Person> findByAddress(String address) { | ||
return super.findByAddress(address); | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public synchronized List<Person> findByPhone(String phone) { | ||
return super.findByPhone(phone); | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
src/main/java/edu/hw7/task3/LockCachingPersonDatabase.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package edu.hw7.task3; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.locks.ReadWriteLock; | ||
import java.util.concurrent.locks.ReentrantReadWriteLock; | ||
import lombok.SneakyThrows; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public class LockCachingPersonDatabase extends AbstractPersonDatabase { | ||
|
||
private final ReadWriteLock lock = new ReentrantReadWriteLock(); | ||
|
||
@SneakyThrows | ||
@Override | ||
public void add(Person person) { | ||
try { | ||
lock.writeLock().lock(); | ||
super.add(person); | ||
} finally { | ||
lock.writeLock().unlock(); | ||
} | ||
} | ||
|
||
@Override | ||
public void delete(int id) { | ||
try { | ||
lock.writeLock().lock(); | ||
super.delete(id); | ||
} finally { | ||
lock.writeLock().unlock(); | ||
} | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public List<Person> findByName(String name) { | ||
try { | ||
lock.readLock().lock(); | ||
return super.findByName(name); | ||
} finally { | ||
lock.readLock().unlock(); | ||
} | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public List<Person> findByAddress(String address) { | ||
try { | ||
lock.readLock().lock(); | ||
return super.findByAddress(address); | ||
} finally { | ||
lock.readLock().unlock(); | ||
} | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public List<Person> findByPhone(String phone) { | ||
try { | ||
lock.readLock().lock(); | ||
return super.findByPhone(phone); | ||
} finally { | ||
lock.readLock().unlock(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package edu.hw7.task3; | ||
|
||
public record Person(int id, String name, String address, String phoneNumber) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package edu.hw7.task3; | ||
|
||
import java.util.List; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public interface PersonDatabase { | ||
void add(Person person); | ||
|
||
void delete(int id); | ||
|
||
@Nullable List<Person> findByName(String name); | ||
|
||
@Nullable | ||
List<Person> findByAddress(String address); | ||
|
||
@Nullable | ||
List<Person> findByPhone(String phone); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package edu.hw7.task4; | ||
|
||
import java.util.Random; | ||
import java.util.concurrent.CountDownLatch; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Future; | ||
import java.util.concurrent.ThreadLocalRandom; | ||
import lombok.SneakyThrows; | ||
import lombok.experimental.UtilityClass; | ||
|
||
@UtilityClass | ||
public class MonteCarloPiComputer { | ||
|
||
private static final double MONTE_CARLO_CONST = 4.0; | ||
private static final double RADIUS = 0.5; | ||
|
||
public static double computePI(long iterationsCount) { | ||
double result = countRandomCollisions(iterationsCount); | ||
return MONTE_CARLO_CONST * (result / iterationsCount); | ||
} | ||
|
||
@SneakyThrows | ||
public static double computePIParallel(long n, int threadCount) { | ||
var executorService = Executors.newFixedThreadPool(threadCount); | ||
double count = 0; | ||
|
||
// Not using atomics here to speed up the process | ||
Future<Long>[] futures = new Future[threadCount]; | ||
CountDownLatch countDownLatch = new CountDownLatch(threadCount); | ||
for (int thread = 0; thread < threadCount; thread++) { | ||
futures[thread] = executorService.submit(() -> { | ||
long countInThread = countRandomCollisions(n / threadCount); | ||
countDownLatch.countDown(); | ||
return countInThread; | ||
}); | ||
} | ||
countDownLatch.await(); | ||
for (int i = 0; i < threadCount; i++) { | ||
count += futures[i].get(); | ||
} | ||
return MONTE_CARLO_CONST * (count / n); | ||
} | ||
|
||
private long countRandomCollisions(long iterationsCount) { | ||
long count = 0; | ||
Random random = ThreadLocalRandom.current(); | ||
for (long i = 0; i < iterationsCount; i++) { | ||
double x = random.nextDouble(); | ||
double y = random.nextDouble(); | ||
if (isInSingleCircle(x, y)) { | ||
count++; | ||
} | ||
} | ||
return count; | ||
} | ||
|
||
private static boolean isInSingleCircle(double x, double y) { | ||
return (x - RADIUS) * (x - RADIUS) + (y - RADIUS) * (y - RADIUS) <= RADIUS * RADIUS; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package edu.hw7.task1; | ||
|
||
import java.util.concurrent.CountDownLatch; | ||
import java.util.concurrent.Executors; | ||
import lombok.SneakyThrows; | ||
import org.assertj.core.api.Assertions; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
|
||
public class MultiCounterTest { | ||
|
||
@SneakyThrows | ||
@Test | ||
@DisplayName("Тестирование MultiCounter#get и MultiCounter#increment") | ||
public void get_shouldReturnCorrectInt_whenIncremented() { | ||
final int threadCount = 5; | ||
var executorService = Executors.newFixedThreadPool(threadCount); | ||
var countDownLatch = new CountDownLatch(threadCount); | ||
var counter = new MultiCounter(); | ||
for (int i = 0; i < threadCount; i++) { | ||
executorService.submit(() -> { | ||
for (int j = 0; j < 1000; j++) { | ||
counter.increment(); | ||
} | ||
countDownLatch.countDown(); | ||
}); | ||
} | ||
countDownLatch.await(); | ||
Assertions.assertThat(counter.get()).isEqualTo(threadCount * 1000); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package edu.hw7.task2; | ||
|
||
import org.assertj.core.api.Assertions; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
|
||
public class ParallelFactorialTest { | ||
|
||
@Test | ||
@DisplayName("Тестирование ParallelFactorial#computeFactorial") | ||
public void computeFactorial_shouldReturnCorrectInt() { | ||
Assertions.assertThat(ParallelFactorial.computeFactorial(5)).isEqualTo(120); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package edu.hw7.task3; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Future; | ||
import lombok.SneakyThrows; | ||
import org.assertj.core.api.Assertions; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import static org.junit.jupiter.api.Assertions.assertAll; | ||
|
||
public class PersonDatabaseTest { | ||
|
||
@Test | ||
@DisplayName("Тестирование LockCachingPersonDatabase") | ||
public void lockDatabase_shouldReturnCorrectPerson_whenPersonAdded() { | ||
PersonDatabase personDatabase = new LockCachingPersonDatabase(); | ||
testDatabase(personDatabase); | ||
} | ||
|
||
@Test | ||
@DisplayName("Тестирование CachingPersonDatabase") | ||
public void synchronizedDatabase_shouldReturnCorrectPerson_whenPersonAdded() { | ||
PersonDatabase personDatabase = new CachingPersonDatabase() { | ||
@SneakyThrows | ||
@Override | ||
public synchronized void add(Person person) { | ||
Thread.sleep(3000); // Imitation of slow database | ||
super.add(person); | ||
} | ||
}; | ||
testDatabase(personDatabase); | ||
} | ||
|
||
@SneakyThrows | ||
private static void testDatabase(PersonDatabase personDatabase) { | ||
var executorService = Executors.newFixedThreadPool(5); | ||
var person = new Person(1, "Ivan", "Moscow", "1234567890"); | ||
executorService.execute(() -> personDatabase.add(person)); | ||
Thread.sleep(100); | ||
Future<List<Person>> futureByPhone = executorService.submit(() -> personDatabase.findByPhone("1234567890")); | ||
Future<List<Person>> futureByName = executorService.submit(() -> personDatabase.findByName("Ivan")); | ||
Future<List<Person>> futureByAddress = executorService.submit(() -> personDatabase.findByAddress("Moscow")); | ||
executorService.shutdown(); | ||
assertAll( | ||
() -> Assertions.assertThat(futureByPhone.get()).contains(person), | ||
() -> Assertions.assertThat(futureByName.get()).contains(person), | ||
() -> Assertions.assertThat(futureByAddress.get()).contains(person) | ||
); | ||
} | ||
|
||
} |
Oops, something went wrong.