consumer class not writing to list Multi threaded application Java - java

I am having a problem with this consumer class.
When i run the program i get an out of bounds exception with each thread in the pool.
I have sysout the list size and it is zero for some reason.
Please see my code below.
I'ts something to with the list being set but i cant figure it out.
Every other part of the program is working and tested just this last part is giving me problems.
Any help offered would be greatly appreciated.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Consumer implements Runnable {
private BlockingQueue<Shingle> q;
private int k;
private int[] minHashes;
private Map<Integer, List<Integer>> map = new HashMap<>();
private ExecutorService pool;
public Consumer(BlockingQueue<Shingle> q, int k, int poolSize) {
super();
this.q = q;
this.k = k;
pool = Executors.newFixedThreadPool(poolSize);
init();
}
public void init() {
Random random = new Random();
minHashes = new int[k];
for (int i = 0; i < minHashes.length; i++) {
minHashes[i] = random.nextInt();
}
}
public void run(){
try {
int docCount = 2;
while (docCount > 0) {
Shingle s = q.take();
if (s instanceof Poision) {
docCount--;
} else {
pool.execute( new Runnable() {
public void run() {
for (int i = 0; i < minHashes.length; i++) {
int value = s.getHashCode() ^ minHashes[i]; // ^ - xor(Random generated key)
List<Integer> list = map.get(s.getDocId());
if (list == null) {
list = new ArrayList<Integer>(k);
for (int j = 0; j < list.size(); j++) {
list.set(j , Integer.MAX_VALUE);
}
map.put(s.getDocId(), list);
} else {
if (list.get(i) > value) {
list.set(i, value);
}
}
}
}
});
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

The issue is that this line
list = new ArrayList<Integer>(k);
create list with initial capacity equal to k not with size equal to k. So your list has 0 elements and the for loop
for (int j = 0; j < list.size(); j++) {
list.set(j , Integer.MAX_VALUE);
}
doesn't execute any iteration. You then add empty list to the map and because of that list.get(i) throws exception.
Please change your for loop to
for (int j = 0; j < minHashes.length; j++) {
list.add(Integer.MAX_VALUE);
}
to actually add elements to list.

Related

I am trying to create a parallel implementation for selection sort but it ends up slower than serial

For my parallel computing class I have to think and create a parallel implementation of the selection sort algorithm. The idea is to be able to scale it to multiple threads so that it becomes faster than the serial implementation.
My idea was as follows:
Parallel selection sort idea
I have created the following implementation over the last few days but it is much slower than the serial algorithm. Whenever I use more threads it is also much slower vs when I use one thread. This is the first time I am working with threads as well so I am not sure if I implemented that correctly.
SelectionSort.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SelectionSort {
private static final int availableProcessors = Runtime.getRuntime().availableProcessors();
private static final int NUMBER_COUNT = 10000;
private static List<Integer> sortedList = new ArrayList<>();
private static int[][] splitArray;
private static List<Integer> lowestNumbers = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
List<Integer> numbers = Numbers.GenerateNumber(NUMBER_COUNT);
class Lowest {
synchronized int getLowest(int index) {
int lowestInArray = Integer.MAX_VALUE;
for (int i = 0; i < splitArray[index].length; i++) {
if (splitArray[index][i] < lowestInArray) {
lowestInArray = splitArray[index][i];
}
}
return lowestInArray;
}
}
Lowest lowest = new Lowest();
class SelectionSortThread extends Thread {
private int splitArrayIndex;
private SelectionSortThread(int splitArrayIndex) {
this.splitArrayIndex = splitArrayIndex;
}
public void run() {
lowestNumbers.add(lowest.getLowest(splitArrayIndex));
}
}
long startingTime = System.currentTimeMillis();
for (int i = 0; i < NUMBER_COUNT; i++) {
List<Thread> threads = new ArrayList<>();
splitArray = fillSplitArray(availableProcessors, numbers);
lowestNumbers.clear();
for (int j = 0; j < availableProcessors; j++) {
if(splitArray[j] != null) {
threads.add(new SelectionSortThread(j));
}
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
int lowestInArray = getLowest(lowestNumbers);
numbers = swap(numbers, lowestInArray);
sortedList.add(numbers.get(0));
numbers.remove(0);
}
System.out.println("Sorted list: " + Arrays.toString(sortedList.toArray()));
System.out.println(System.currentTimeMillis() - startingTime);
}
private static int getLowest(List<Integer> lowestNumbers) {
int lowestInArray = Integer.MAX_VALUE;
for (Integer lowestNumber : lowestNumbers) {
if (lowestNumber < lowestInArray) {
lowestInArray = lowestNumber;
}
}
return lowestInArray;
}
private static List<Integer> swap(List<Integer> list, int lowest)
{
int n = list.size();
for(int i = 0; i < n; i++)
{
if(list.get(i) == lowest) {
Collections.swap(list, 0, i);
return list;
}
}
return null;
}
static int[][] fillSplitArray(int arrayAmount, List<Integer> listToUse) {
if (listToUse.size() == 0) {
return new int[0][0];
}
int splitLength = (int) Math.ceil((double) listToUse.size() / (double) arrayAmount);
int[][] splits = new int[arrayAmount][];
int j = 0;
int k = 0;
for (int i = 0; i < listToUse.size(); i++) {
if (k == splitLength) {
k = 0;
j++;
}
if (splits[j] == null) {
int remainingNumbers = listToUse.size() - i;
splits[j] = new int[Math.min(remainingNumbers, splitLength)];
}
splits[j][k++] = listToUse.get(i);
}
return splits;
};
}
Numbers.java
import java.util.ArrayList;
import java.util.List;
class Numbers {
static List<Integer> GenerateNumber(int numberCount) {
List<Integer> temp = new ArrayList<>();
for (int i = numberCount; i > 0; i--) {
temp.add(i);
}
return temp;
}
}
Is there anything I am doing totally wrong or that I could improve? I am expecting the parallel implementation to be faster than the serial one but so far this is not the case. It is currently a lot slower.

== null Doesn't work java

I have made a function for objects to reserve seats in a area. But if 2 objects enter the function at the same time they get the same seats. How do I solve this?
The Function getFreeChairs, returns the chair positions. And sets the Fan. But if two fans enter it at the same time they both get the same seats.
Sven
package model;
import actors.Fan;
import java.util.ArrayList;
import java.util.List;
/**
* Created by sveno on 12-10-2016.
*/
public class Vak {
private static int autoId = 1;
private String naam;
private int rijen, stoelenperrij, id;
private List<ArrayList> rows = new ArrayList<>();
private Fan fan = null;
public Vak(String naam, int rijen, int stoelenperrij) {
this.naam = naam;
this.rijen = rijen;
this.stoelenperrij = stoelenperrij;
this.id = autoId;
autoId++;
for (int i = 0; i < rijen; i++) {
rows.add(new ArrayList<Fan>());
}
for (ArrayList row : rows) {
for (int j = 0; j < stoelenperrij; j++) {
row.add(fan);
}
}
}
public void removeReserved(int rij, List<Integer> stoelen){
for (int i = 0; i < stoelen.size()-1; i++) {
//De reserveer alle stoelen
ArrayList<Fan> stoel = rows.get(rij);
stoel.set(stoelen.get(i),fan);
}
}
public int getRijen() {
return rijen;
}
public int getStoelenperrij() {
return stoelenperrij;
}
public List<ArrayList> getRows() {
return rows;
}
public int[] getFreeChairs(int aantalStoelen, Fan fan){
//Check for free seats
int count = 1;
int[] stoelenleeg = new int[aantalStoelen+1];
for (int j = 0; j < rows.size(); j++) {
for (int k = 0; k < rows.get(j).size(); k++) {
if (rows.get(j).get(k) == null){
stoelenleeg[count-1] = k;
count++;
//Not enough seats next to each other
if(count==aantalStoelen+1){
stoelenleeg[aantalStoelen] = j+1;
for (int o = 0; o < stoelenleeg.length-1; o++) {
ArrayList<Fan> stoel = rows.get(j);
stoel.set(stoelenleeg[o],fan);
}
return stoelenleeg;
}
}else{
//Not enough seats
stoelenleeg = new int[aantalStoelen+1];
count=1;
}
}
}
return stoelenleeg;
}
}
If your code is used in a concurrent context (multiple threads), you need to make sure that your code is thread safe.
It means that, only one single thread(person) should be able to call the getFreeChairs function(reserve a seat at a time)
The easy way to do it in java is to use the synchronized key word in the method definition:
public synchronized int[] getFreeChairs(int aantalStoelen, Fan fan){
...
}

Recursion n over k Multi Thread (user input)

I tried to reprogramm this and fit it to my needs (calculating n^k with recursion). But something seems faulty, because I first got the txt files without any text in it; now after changing and trying to bugfix I get nothing at all :(
https://www.youtube.com/watch?v=br_TEuE8TbY
package Uebung3;
import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import javax.swing.JOptionPane;
public class Hauptthread implements Runnable {
//int start;
//int stop;
boolean haupt=false;
String file;
static int n, k;
public Hauptthread(int startvalue, int stopvalue, String file, boolean h){
n= startvalue;
k=stopvalue;
this.file=file;
haupt=h;
}
public void run(){
ArrayList<Double> binominal=new ArrayList<>();
if (haupt=false) {
for (int i = n; i <= k; i++) {
binominal.add(binomial(n,k));
}
try{
PrintWriter print=new PrintWriter(new File(file));
for (int i = 0; i < binominal.size() ; i++) {
print.println("Test");
print.println(binominal.get(i));
}
}
catch(Exception e){
System.out.println("Error " + e.getMessage());
}
}
}
double binomial(int n, int k) {
if (k == 0) {
return 1; }
else {
return (((double)n/k) * binomial(n-1, k-1)); }
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
package Uebung3;
import java.util.ArrayList;
import javax.swing.JOptionPane;
public class Uebung3 {
public static int threadcount=4;
public static int n, k;
public static int stop=k;
public static void main(String[] args) {
/*
int n = Integer.parseInt(JOptionPane.showInputDialog("n = "));
int k = Integer.parseInt(JOptionPane.showInputDialog("k = "));
if (n < 0 || k < 0 || k > n) {
JOptionPane.showMessageDialog(null, "Ungueltige Eingabe"); }
else {
JOptionPane.showMessageDialog(null, "Rechne" );
//JOptionPane.showMessageDialog(null, "n über k = " +binomial(n, k));
}
*/
System.out.println("Erstelle Threads...");
int erhoehe=20/threadcount;
int start=2;
ArrayList <Thread> threads = new ArrayList<>();
for (int i = 0; i < threadcount; i++) {
//if(!((i+1)==threadcount)){
if(start==10){
threads.add(new Thread(new Hauptthread(start, erhoehe, i+".txt",false)));
}
else {
threads.add(new Thread(new Hauptthread(start, erhoehe, i+".txt",true)));
}
}
for (int i = 0; i < threads.size(); i++) {
threads.get(i).start();
}
for (int i = 0; i < threads.size(); i++) {
try {
threads.get(i).join();
} catch (Exception e) {
System.out.println("Error" +e.getMessage());
}
}
}
}

My function seems to be editing multiple objects

In my Sudoku Android application I have a solve function that solves a Sudoku puzzle (a CellField object). However for some reason when I clone a CellField object and I call the solve method on the cloned object, the solve method solves both of the CellField objects but I only want it to solve the cloned CellField object and not the original object. Any suggestions? Thanks
Here I clone the CellField object (the clone is called temp) and also call the solve method
CellField temp = null;
try {
temp = board.cf.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
int x = randInt(0,8);
int y = randInt(0,8);
while (!temp.getCell(y,x).isEditable && board.cf.getCell(y,x).getValue() == 0) {
x = randInt(0,8);
y = randInt(0,8);
}
SudokuSolver solver = new SudokuSolver();
solver.solve(temp);
Here is my solve method and SudokuSolver class
package com.example.czhou.myapplication2;
import java.util.*;
public class SudokuSolver {
static boolean retry;
public static int randInt(ArrayList<Integer> candidates) {
int min = 0;
int max = candidates.size() - 1;
//inclusive
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
int result = candidates.get(randomNum);
candidates.remove(randomNum);
return result;
}
public boolean solve(CellField field) {
// write your code here
boolean isValid = true;
Set<Integer> toRemove = new HashSet<>();
int i;
int j;
for (int k = 0; k < 9; k++) {
for (int l = 0; l < 9; l++) {
field.getCell(k, l).restAlt();
if (field.getCell(k, l).alt.indexOf(field.getCell(k, l).getValue()) != -1) {
field.getCell(k, l).alt.remove(field.getCell(k, l).alt.indexOf(field.getCell(k, l).getValue()));
}
}
}
for (i = 0; i < 9; i++) {
for (j = 0; j < 9; j++) {
if (field.getCell(i,j).getValue() == 0 && field.getCell(i,j).alt.size() == 0){
field.getCell(i,j).restAlt();
}
if (field.getCell(i, j).isEditable) {
toRemove.clear();
for (int k = 0; k < 9; k++) {
toRemove.add(field.getCell(k, j).getValue());
}
toRemove.addAll(field.getSectorCandidates(i, j));
for (int k = 0; k < 9; k++) {
toRemove.add(field.getCell(i, k).getValue());
}
toRemove.removeAll(Collections.singleton(0));
field.getCell(i, j).alt.removeAll(toRemove);
if (toRemove.size() == 9 || field.getCell(i, j).alt.size() == 0) {
//When there no candidates are available
//in the current cell, come here
//toRemove.clear();
Cell cell;
boolean stop = false;
backtrack:
for (int k = j; !stop; k--) {
if (k == -1) {
if (i != 0) {
--i;
} else {
break;
}
k = 8;
}
j = k;
// Scan for previous cells have alternative candidates
cell = field.getCell(i, k);
if (cell.alt.size() > 0 && cell.isEditable) {
//bookmark the original cell
//int nextCell = k+1;
// If found a cell set value as first alternative
cell.setValue(cell.alt.get(0));
break backtrack;
} else if (cell.isEditable){
// if no alternatives set cell to 0 and continue backwards
cell.setValue(0);
}
}
} else {
field.getCell(i, j).setValue(randInt(field.getCell(i, j).alt));
}
}
}
}
// for (int m = 0; m < 9; m++) {
// for (int l = 0; l < 9; l++) {
// if (l == 0) {
// System.out.println();
// }
// System.out.print(field.getCell(m, l).getValue());
// }
// }
// System.out.println();
// System.out.println("================");
return isValid;
}
}
Here is my CellField class
package com.example.czhou.myapplication2;
import android.util.Log;
import java.io.Serializable;
import java.util.*;
import java.util.regex.Matcher;
public class CellField implements Cloneable{
protected Cell[][] field = new Cell[9][9];
public CharSequence timeElapsed = "00:00";
public CellField() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
field[i][j] = new Cell();
}
}
}
public CellField(CellField another) {
List<Cell[]> cellfield = Arrays.asList(another.field);
this.field = (Cell[][]) cellfield.toArray();
}
public CellField clone() throws CloneNotSupportedException {
return (CellField)super.clone();
}
}
The problem is with you Clone method, as #ρяσѕρєя said, you should do a deep copy. Because right now you are returning the same reference. Try something like this:
public CellField clone() throws CloneNotSupportedException {
CellField clone = new CellField();
clone.field = this.field;
clone.timeElapsed = this.timeElapsed;
return clone;
}
It is a matter of shallow copy versus deep copy.
class SomeClass implements Cloneable {
// This is the problematic field. It doesn't get cloned the way you think it is.
public Integer[] field = new Integer[5];
public SomeClass clone() throws CloneNotSupportedException {
return (SomeClass) super.clone();
}
}
public class HelloWorld {
public static void main(String []args){
SomeClass first = new SomeClass();
SomeClass second = null;
try {
second = first.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(first.field);
System.out.println(second.field);
// Their addresses in memory are the same
// Modifying one would modify the other
// first.field == second.field -> true
}
}
In the above example, I cloned one instance of the class into another and, yet, they share the same field. Mutating fields of the first instance of the class will directly affect the field in the second instance of the class since they both own a reference to it.
Instead of using Cloneable, you could define a copy constructor and perform the cloning on your own.
More advanced details can be found on How to properly override clone method?

recursive method not properly executing

I have a programming assignment for an introductory level Java class (the subset sum problem) - for some reason, my recursive method isn't executing properly (it just goes straight to the end of the method and prints out the sorted list). Any help would be appreciated - I'm a newbie and recursive functions are really confusing to me.
package programmingassignment3;
import java.io.*;
import java.util.*;
public class ProgrammingAssignment3 {
static int TARGET = 10;
static ArrayList<Integer> list = new ArrayList<>();
static int SIZE = list.size();
public static void main(String[] args) {
populateSortSet();
sumInt(list);
recursiveSS(list);
}//main
public static void populateSortSet() {
try {
File f = new File("set0.txt");
Scanner input = new Scanner(f);
while (input.hasNext()) {
int ele = input.nextInt();
if (ele < TARGET && !list.contains(ele)) {
list.add(ele);
}//if
}//while
Collections.sort(list);
}//try
catch (IOException e) {
e.printStackTrace();
}//catch
}//populateSet
public static void recursiveSS(ArrayList<Integer> Alist) {
if (Alist.size() == SIZE) {
if (sumInt(Alist) == TARGET) {
System.out.println("The integers that equal " + TARGET + "are: " + Alist);
} //if==TARGET
}//if==SIZE
else {
for (int i = 0; i < SIZE; i++) {
ArrayList<Integer> list1 = new ArrayList<>(Alist);
ArrayList<Integer> list0 = new ArrayList<>(Alist);
list1.add(1);
list0.add(0);
if (sumInt(list0) < TARGET) {
recursiveSS(list0);
}//if
if (sumInt(list1) < TARGET) {
recursiveSS(list1);
}//if
}//for
}//else
System.out.println("echo" + Alist);
}//recursiveSS
public static int sumInt(ArrayList<Integer> Alist) {
int sum = 0;
for (int i = 0; i < SIZE - 1; i++) {
sum += Alist.get(i);
}//for
if (Alist.size() == TARGET) {
sum += Alist.get(Alist.size() - 1);
}//if
return sum;
}//sumInt
}//class
This thing that you do at class level:
static ArrayList<Integer> list = new ArrayList<>();
static int SIZE = list.size();
means that SIZE will be initiated to 0, and stay 0 (even if you add elements to the list.)
This means that the code inside the for-loop will be executed 0 times.
Try something like:
public class ProgrammingAssignment3 {
private static int initialSize;
//...
public static void populateSortSet() {
//populate the list
initialSize = list.size();
}
So you don't set the value of the size variable until the list is actually populated.
That being said, there a quite a few other strange things in your code, so I think you need to specify exactly what you are trying to solve here.
Here's how I'd do it. I hope it clarifies the stopping condition and the recursion. As you can see, static methods are not an issue:
import java.util.ArrayList;
import java.util.List;
/**
* Demo of recursion
* User: mduffy
* Date: 10/3/2014
* Time: 10:56 AM
* #link http://stackoverflow.com/questions/26179574/recursive-method-not-properly-executing?noredirect=1#comment41047653_26179574
*/
public class RecursionDemo {
public static void main(String[] args) {
List<Integer> values = new ArrayList<Integer>();
for (String arg : args) {
values.add(Integer.valueOf(arg));
}
System.out.println(String.format("input values : %s", values));
System.out.println(String.format("iterative sum: %d", getSumUsingIteration(values)));
System.out.println(String.format("recursive sum: %d", getSumUsingRecursion(values)));
}
public static int getSumUsingIteration(List<Integer> values) {
int sum = 0;
if (values != null) {
for (int value : values) {
sum += value;
}
}
return sum;
}
public static int getSumUsingRecursion(List<Integer> values) {
if ((values == null) || (values.size() == 0)) {
return 0;
} else {
if (values.size() == 1) { // This is the stopping condition
return values.get(0);
} else {
return values.get(0) + getSumUsingRecursion(values.subList(1, values.size())); // Here is recursion
}
}
}
}
Here is the case I used to test it:
input values : [1, 2, 3, 4, 5, 6]
iterative sum: 21
recursive sum: 21
Process finished with exit code 0
Thanks everyone. I really appreciate the help. I did figure out the problem and the solution is as follows (closing brace comments removed for the reading pleasure of #duffymo ):
public class ProgrammingAssignment3 {
static int TARGET = 6233;
static ArrayList<Integer> set = new ArrayList<>();
static int SIZE;
static int count = 0;
public static void populateSortSet() {
try {
File f = new File("set3.txt");
Scanner input = new Scanner(f);
while (input.hasNext()) {
int ele = input.nextInt();
if (ele < TARGET && !set.contains(ele)) {
set.add(ele);
}
}
Collections.sort(set);
SIZE = set.size();
System.out.println("The original sorted set: " + set + "\t subset sum = " + TARGET);
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void recursiveSS(ArrayList<Integer> list) {
if (list.size() == SIZE) {
if (sumInt(list) == TARGET) {
System.out.print("The Bit subset is: " + list + "\t");
System.out.println("The subset is: " + getSubset(list));
count++;
}
}
else {
ArrayList<Integer> list1 = new ArrayList<>(list);//instantiate list1
ArrayList<Integer> list0 = new ArrayList<>(list);//instantiate list0
list1.add(1);
list0.add(0);
if (sumInt(list0) <= TARGET) {
recursiveSS(list0);
}
if (sumInt(list1) <= TARGET) {
recursiveSS(list1);
}
}
}
public static int sumInt(ArrayList<Integer> list) {
int sum = 0;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 1) {
sum += set.get(i);
}
}
return sum;
}
public static ArrayList<Integer> getSubset(ArrayList<Integer> list) {
ArrayList<Integer> l = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 1) {
l.add(set.get(i));
}
}
return l;
}
}

Categories