Commit 68b2a772 authored by Gabriele Civitarese's avatar Gabriele Civitarese

first commit

parents
package callable;
import java.util.concurrent.Callable;
public class FactorialCallable implements Callable<Long> {
private int number;
public FactorialCallable(int number){
this.number = number;
}
@Override
public Long call() {
Long result = 1L;
for(int i = 1; i<=number; i++)
result*=i;
return result;
}
}
package callable;
import java.util.HashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static void main(String[] args) {
//data structure to store mapping between the computed value and the input value
HashMap<Future<Long>, Integer> futureMap = new HashMap<>();
ExecutorService executorService = Executors.newCachedThreadPool();
//let's compute factorial of numbers from 2 to 10
for(int i = 2; i<=10; i++){
System.out.println("Computing factorial of "+i);
//we insert into the map the association between future and input value
futureMap.put(executorService.submit(new FactorialCallable(i)),i);
}
//for each future
for(Future<Long> future: futureMap.keySet()){
try {
//get the answer
Long answer = future.get();
System.out.println("The factorial of "+futureMap.get(future)+" is: "+answer);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
//always shutdown executors
executorService.shutdown();
}
}
package conditions;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BoundedBuffer<T> {
//defining a lock. a reentrant lock has the same behavior of intrinsic monitor
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private T items[];
private int count, putptr, takeptr;
public BoundedBuffer(int size){
items = (T[]) new Object[size];
count = 0;
putptr = 0;
takeptr = 0;
}
public void put(T t) throws InterruptedException{
//for a thread it has the same behavior of entering a synchronized area
lock.lock();
try{
//until the buffer is full
while(count == items.length) {
System.out.println("Buffer pieno. In attesa di consumatori");
//wait on the condition related to full buffer
//this will release the lock similarly to wait()
notFull.await();
}
//when we reach here, we are sure that the buffer is not full
items[putptr] = t;
//the put pointer is circular
if(++putptr == items.length)
putptr = 0;
//we added an element
++count;
//this is similar to notify()
//if someone is waiting because the buffer is empty, let's wake it up
notEmpty.signal();
}finally {
//to guarantee fairness, we always need to relase the lock
//equivalent to exiting a synchronized area
lock.unlock();
}
}
public T take() throws InterruptedException{
//the lock HAS to be the same as before, like for synchronized blocks
lock.lock();
try{
//if there are no elements to read, wait
while(count==0){
System.out.println("Buffer vuoto. In attesa di produttori.");
notEmpty.await();
}
//take the item pointed by takeptr
T item = items[takeptr];
//also this pointer is circular
if(++takeptr == items.length)
takeptr = 0;
//we retrieved an element
--count;
//notify the threads sleeping on the full buffer condition
notFull.signal();
return item;
}
finally {
lock.unlock();
}
}
}
package conditions;
public class Consumer implements Runnable {
private final BoundedBuffer<String> boundedBuffer;
private final String id;
public Consumer(String id, BoundedBuffer<String> boundedBuffer) {
this.id = id;
this.boundedBuffer = boundedBuffer;
}
public void run() {
try {
while(true) {
consume(boundedBuffer.take());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void consume(String message) {
System.out.println("Cons. " + id + ": prelevato " + message);
}
}
\ No newline at end of file
package conditions;
public class Main {
public static void main(String[] args) {
int producers = 5;
int consumers = 5;
BoundedBuffer<String> boundedBuffer = new BoundedBuffer<>(5);
for(int i = 0; i<consumers; i++)
new Thread(new Consumer("c"+i, boundedBuffer)).start();
for(int i = 0; i<producers; i++)
new Thread(new Producer("p"+i, boundedBuffer)).start();
}
}
package conditions;
public class Producer implements Runnable {
private final String id;
private BoundedBuffer<String> boundedBuffer;
public Producer(String id, BoundedBuffer<String> boundedBuffer) { this.id = id; this.boundedBuffer = boundedBuffer; }
public void run() {
while (true) {
try {
String message = produce();
System.out.println("Prod. " + id + ": inserisco " + message);
boundedBuffer.put(message);
//Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private int counter = 0;
public String produce() {
counter++;
return "Messaggio da " + id + " n. " + counter;
}
}
package countdownlatches;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
int numberOfThreads = 5;
//creating an executor with a fixed number of threads
ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
//creating a countdown which has exactly the number of threads we want to launch
CountDownLatch countDownLatch = new CountDownLatch(numberOfThreads);
//let's start all the threads with the executor
for(int i = 0; i < numberOfThreads; i++){
executorService.submit(new Worker(countDownLatch));
}
System.out.println("Waiting for thread termination...");
try {
//blocking until all the threads executed countDown()
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All the threads concluded their work.");
executorService.shutdown();
}
}
package countdownlatches;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class Worker implements Runnable {
private Random rnd;
private CountDownLatch countDownLatch;
public Worker(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
this.rnd = new Random();
}
@Override
public void run() {
System.out.println("["+Thread.currentThread()+"] Thread started!");
wasteSomeTime();
System.out.println("["+Thread.currentThread()+"] Goodbye.");
//decrease the countdown
countDownLatch.countDown();
}
private void wasteSomeTime() {
int seconds = rnd.nextInt(10) + 1;
try {Thread.sleep(seconds*1000);}
catch(Exception ex) {ex.printStackTrace();}
}
}
package forkjoinpool;
import java.util.concurrent.ForkJoinPool;
public class Main {
public static void main(String[] args) {
//initializing forkJoinPool. 4 is the number of threads, the better parameter is the number of available cores.
ForkJoinPool forkJoinPool = new ForkJoinPool(4);
//initializing a recursive task
MyRecursiveTask myRecursiveTask = new MyRecursiveTask(1024);
//invoking the task. it is blocking until the final result is computed
long mergedResult = forkJoinPool.invoke(myRecursiveTask);
System.out.println("merged result = "+mergedResult);
}
}
package forkjoinpool;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.RecursiveTask;
public class MyRecursiveTask extends RecursiveTask<Long> {
//this variable simulates the amount of work of a specific task
private long workload = 0;
public MyRecursiveTask(long workload){
this.workload = workload;
}
//it is important to override this method
//it defines what a task does
@Override
protected Long compute() {
//recursive condition
//if the workload is "too much"
if(this.workload > 16){
//we create subtasks to split the work
List<MyRecursiveTask> subtasks = new ArrayList<>();
//add subtasks to the list of subtasks
subtasks.addAll(createSubtasks());
//for each subtask we call the fork() method.
for(MyRecursiveTask subtask: subtasks){
subtask.fork();
}
//after each subtask is forked, we need to define what to do to merge things
long result = 0;
//joining the results of subtasks
for(MyRecursiveTask subtask: subtasks){
result += subtask.join();
}
return result;
}
//base step of recursion: if the workload is <16
return workload*3;
}
//method to split work in subtaks
private List<MyRecursiveTask> createSubtasks() {
List<MyRecursiveTask> subtasks = new ArrayList<>();
//we simply divide the workload to two subtasks
MyRecursiveTask subtask1 = new MyRecursiveTask(this.workload/2);
MyRecursiveTask subtask2 = new MyRecursiveTask(this.workload/2);
subtasks.add(subtask1);
subtasks.add(subtask2);
return subtasks;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment