I have this class:
package metodo_java8_moderno;
import java.util.ArrayList;
import java.util.List;
public class SingleThreadClass {
public List<Object> editAndAdd(List<List<Long>> matrix){
Long limit = (long) matrix.get(0).size()*matrix.size()/2;
List<Long> numbers = new ArrayList<>();
for(int i=0; i<matrix.get(0).size(); i++){
for(int j=0; j<matrix.size(); j++){
if(matrix.get(j).get(i).longValue() <= limit){
numbers.add(matrix.get(j).get(i));
matrix.get(j).set(i,null);
}
}
}
List<Object> objectList = new ArrayList<>();
objectList.add(matrix);
objectList.add(numbers);
return objectList;
}
}
I want to parallel only the following piece by exploiting all the cores of my CPU:
for(int j=0; j<matrix.size(); j++){
if(matrix.get(j).get(i).longValue() <= limit){
numbers.add(matrix.get(j).get(i));
matrix.get(j).set(i,null);
}
}
I get an error and I believe it is due to the sharing of objects between different threads.
I post all the code of my work:
ElementMutator.java
package metodo_java8_moderno;
@FunctionalInterface
public interface ElementMutator<T> {
void apply(int i);
}
ForkJoinListMutator.java
package metodo_java8_moderno;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class ForkJoinListMutator {
public static final int DEFAULT_SEQ_THRESHOLD = 10000;
private static final ForkJoinListMutator defaultInstance = new ForkJoinListMutator(ForkJoinPool.commonPool());
private final ForkJoinPool forkJoinPool;
public ForkJoinListMutator(ForkJoinPool forkJoinPool) {
this.forkJoinPool = forkJoinPool;
}
public static ForkJoinListMutator getDefault() {
return defaultInstance;
}
public <T> void mutate(List<T> list, ElementMutator<T> mutator) {
mutate(list, DEFAULT_SEQ_THRESHOLD, mutator);
}
public <T> void mutate(List<T> list, int seqThreshold, ElementMutator<T> mutator) {
MutateTask<T> mainTask = new MutateTask<>(list, seqThreshold, mutator);
forkJoinPool.invoke(mainTask);
}
private static class MutateTask<T> extends RecursiveAction {
private final List<T> list;
private final int start;
private final int end;
private final int seqThreshold;
private final ElementMutator<T> mutator;
public MutateTask(List<T> list, int seqThreshold, ElementMutator<T> mutator) {
this(list, 0, list.size(), seqThreshold, mutator);
}
public MutateTask(List<T> list, int start, int end, int seqThreshold, ElementMutator<T> mutator) {
this.list = list;
this.start = start;
this.end = end;
this.seqThreshold = seqThreshold;
this.mutator = mutator;
}
@Override
protected void compute() {
final int length = end - start;
if (length <= seqThreshold) {
computeSequentially();
} else {
MutateTask<T> leftTask = new MutateTask<>(list, start, start+length/2, seqThreshold, mutator);
leftTask.fork();
leftTask.join();
MutateTask<T> rightTask = new MutateTask<>(list, start+length/2, end, seqThreshold, mutator);
rightTask.compute();
}
}
private void computeSequentially() {
for (int i = start; i < end; i++) {
mutator.apply(i);
}
}
}
}
ForkJoinListMutatorExample.java
package metodo_java8_moderno;
import java.util.List;
public class ForkJoinListMutatorExample {
public static void main(String args[]) {
GenerateMatrix generateMatrix = new GenerateMatrix();
List<List<Long>> matrix = generateMatrix.generate(3,4);
System.out.println(matrix);
long t1 = System.nanoTime();
SingleThreadClass singleThreadClass = new SingleThreadClass();
List<Object> output = singleThreadClass.editAndAdd(matrix);
long t2 = System.nanoTime();
System.out.println("Time taken single thread process: " + (t2-t1)/100000000);
List<List<Long>> newMatrix = (List<List<Long>>) output.get(0);
List<Long> numbers = (List<Long>) output.get(1);
System.out.println(newMatrix);
System.out.println(numbers);
t1 = System.nanoTime();
MultiThreadClass multiThreadClass = new MultiThreadClass();
output = multiThreadClass.editAndAdd(matrix);
t2 = System.nanoTime();
System.out.println("Time taken multi thread process: " + (t2-t1)/100000000);
List<List<Long>> newMatrix2 = (List<List<Long>>) output.get(0);
List<Long> numbers2 = (List<Long>) output.get(1);
System.out.println(newMatrix2);
System.out.println(numbers2);
}
}
GenerateMatrix.java
package metodo_java8_moderno;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class GenerateMatrix {
public List<List<Long>> generate(int columns, int rows){
List<List<Long>> matrix = new ArrayList<>();
List<Long> row;
Random randomGenerator = new Random();
for(int i=0; i<rows; i++){
row = new ArrayList<>();
for(int j=0; j<columns; j++){
row.add((long) randomGenerator.nextInt(columns*rows+1));
}
matrix.add(row);
}
return matrix;
}
}
MultiThreadClass.java
package metodo_java8_moderno;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MultiThreadClass {
private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
public List<List<Long>> matrix;
public void setMatrix(List<List<Long>> matrix) {
reentrantReadWriteLock.writeLock().lock();
try {
this.matrix = matrix;
} catch (Exception e){
this.matrix = null;
} finally {
reentrantReadWriteLock.writeLock().unlock();
}
}
public List<List<Long>> getMatrix() {
reentrantReadWriteLock.readLock().lock();
List<List<Long>> matrix;
try {
matrix = this.matrix;
} catch (Exception e){
matrix = null;
} finally {
reentrantReadWriteLock.readLock().unlock();
}
return matrix;
}
public int i;
public void setI(int i) {
reentrantReadWriteLock.writeLock().lock();
try {
this.i = i;
} catch (Exception e){
this.i = -1;
} finally {
reentrantReadWriteLock.writeLock().unlock();
}
}
public int getI() {
reentrantReadWriteLock.readLock().lock();
int i;
try {
i = this.i;
} catch (Exception e){
i = -1;
} finally {
reentrantReadWriteLock.readLock().unlock();
}
return i;
}
public List<Long> numbers;
public void setNumbers(List<Long> numbers) {
reentrantReadWriteLock.writeLock().lock();
try {
this.numbers = numbers;
} catch (Exception e){
this.numbers = null;
} finally {
reentrantReadWriteLock.writeLock().unlock();
}
}
public List<Long> getNumbers() {
reentrantReadWriteLock.readLock().lock();
List<Long> numbers;
try {
numbers = this.numbers;
} catch (Exception e){
numbers = null;
} finally {
reentrantReadWriteLock.readLock().unlock();
}
return numbers;
}
public Long limit;
public void setLimit(Long limit) {
reentrantReadWriteLock.writeLock().lock();
try {
this.limit = limit;
} catch (Exception e){
this.limit = null;
} finally {
reentrantReadWriteLock.writeLock().unlock();
}
}
public Long getLimit() {
reentrantReadWriteLock.readLock().lock();
Long limit;
try {
limit = this.limit;
} catch (Exception e){
limit = null;
} finally {
reentrantReadWriteLock.readLock().unlock();
}
return limit;
}
public List<Object> editAndAdd(List<List<Long>> matrix){
this.matrix = matrix;
this.limit = (long) this.matrix.get(0).size()*this.matrix.size()/2;
this.numbers = new ArrayList<>();
int core = Runtime.getRuntime().availableProcessors();
for(int i=0; i<this.matrix.get(0).size(); i++){
this.i = i;
ForkJoinListMutator listMutator = ForkJoinListMutator.getDefault();
listMutator.mutate(this.matrix,Math.max(1,this.matrix.size()/(core*1+1)),(j) -> parallelFor(j));
}
List<Object> objectList = new ArrayList<>();
objectList.add(this.matrix);
objectList.add(this.numbers);
return objectList;
}
public void parallelFor(int j){
try{
List<List<Long>> matrix = getMatrix();
int i = getI();
List<Long> numbers = getNumbers();
Long limit = getLimit();
if(matrix.get(j).get(i).longValue() <= limit){
numbers.add(matrix.get(j).get(i));
matrix.get(j).set(i,null);
}
setMatrix(matrix);
setI(i);
setNumbers(numbers);
setLimit(limit);
//System.out.println(">> "+this.matrix);
//System.out.println(">> "+this.numbers);
}catch (Exception e){
System.out.println("Errore!");
System.out.println(e.getMessage());
System.out.println(e.getCause());
}
}
}
SingleThreadClass.java
package metodo_java8_moderno;
import java.util.ArrayList;
import java.util.List;
public class SingleThreadClass {
public List<Object> editAndAdd(List<List<Long>> matrix){
Long limit = (long) matrix.get(0).size()*matrix.size()/2;
List<Long> numbers = new ArrayList<>();
for(int i=0; i<matrix.get(0).size(); i++){
for(int j=0; j<matrix.size(); j++){
if(matrix.get(j).get(i).longValue() <= limit){
numbers.add(matrix.get(j).get(i));
matrix.get(j).set(i,null);
}
}
}
List<Object> objectList = new ArrayList<>();
objectList.add(matrix);
objectList.add(numbers);
return objectList;
}
}