I have a merge-sort algorithm that splits an unsorted array into multiple buckets as specified in the main method. I am required to have multiple threads where each thread does work on a single bucket to sort the numbers in that bucket and then merge the results together. How do i go about it given the following piece of code. i have done so...managed to create threads proportional to the number of array buckets...but now how do i assign the buckets to each thread worker...i have edited the code in the posting please.
public class Test{
public static void main(String[] args) {
int[] numsToSort = {1,5,3,7,10,4,6,11,2,8,9,12,16,14,17,13,19,20};
int[] sorted = bucketSort(numsToSort,3);
System.out.print("Sorted: ");
for (int i = 0; i < sorted.length; i++) {
System.out.print(sorted[i] + " ");
}
}
public static int[] bucketSort(int[] numbers, int bucketCount) {
if (numbers.length <= 1)
return numbers;
int maxVal = numbers[0];
int minVal = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > maxVal)
maxVal = numbers[i];
if (numbers[i] < minVal)
minVal = numbers[i];
}
double interval = ((double) (maxVal - minVal + 1)) / bucketCount; // range of bucket
ArrayList<Integer> buckets[] = new ArrayList[bucketCount];
for (int i = 0; i < bucketCount; i++) // initialize buckets (initially empty)
buckets[i] = new ArrayList<Integer>();
for (int i = 0; i < numbers.length; i++) // distribute numbers to buckets
buckets[(int) ((numbers[i] - minVal) / interval)].add(numbers[i]);
int k = 0;
//=======================================
for (int i = 0; i < buckets.length; i++) {
ExecutorService executor = Executors.newFixedThreadPool(3);
//System.out.println("buckets " + i + " " + buckets[i]);
//submitting tasks
//for (int i = 0; i <5; i++) {
executor.submit(new App(i));
Collections.sort(buckets[i]); // calls Java's built-in merge sort(as a kind of “helper” sort)
for (int j = 0; j < buckets[i].size(); j++) { // update array with the bucket content
numbers[k] = buckets[i].get(j);
k++;
}
//}
executor.shutdown();
System.out.println("All tasks submitted...");
try {
executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("All tasks completed...");
}
return numbers;
}
}
class App implements Runnable{
private int id;
public App(int id){
this.id = id;
}
#Override
public void run() {
System.out.println("starting..." + id);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("completed..." + id);
}
}
Here is an SSCCE, while the approach is a bit different than yours (Java 8) it accomplishes what I believe you question described.
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ThreadSorter
{
private static Random random = new Random();
public static void main(String[] args)
{
List<Integer> numsToSort = random.ints(0, 50).limit(60L).boxed()
.collect(Collectors.toList());
ThreadSorter testClass = new ThreadSorter();
List<Integer> sorted = testClass.bucketSort(numsToSort, 4);
System.out.print("Sorted: ");
sorted.stream().forEach(i -> System.out.print(i + " "));
}
public List<Integer> bucketSort(List<Integer> numbers, int bucketCount)
{
if (numbers.size() <= 1)
return numbers;
Queue<ArrayList<Integer>> buckets = new LinkedList<ArrayList<Integer>>();
// create buckets
buckets.addAll(IntStream.range(0, bucketCount)
.mapToObj(i -> new ArrayList<Integer>()).collect(Collectors.toList()));
// iterate numbers adding to current bucket (revolving queue additions)
for (int i = 0; i < numbers.size(); i++)
{
ArrayList<Integer> currentBucket = buckets.poll();
currentBucket.add(numbers.get(i));
buckets.offer(currentBucket);
}
// LinkedList is a queue and a list :)
List<ArrayList<Integer>> bucketList = (List<ArrayList<Integer>>) buckets;
for (int i = 0; i < bucketList.size(); i++)
{
System.out.println("buckets " + i + ": " + bucketList.get(i));
}
// create Threads for each bucket
List<Thread> threads = bucketList.stream()
.map(e -> new Thread(new BucketSorter(e))).collect(Collectors.toList());
// start threads
threads.stream().forEach(Thread::start);
// join threads (make sure all are complete before continuing)
for (Thread t : threads)
{
try
{
t.join();
}
catch (InterruptedException e1)
{}
}
// debug statement shoing individual buckets are sorted
for (int i = 0; i < bucketList.size(); i++)
{
System.out.println("sorted buckets " + i + ": " + bucketList.get(i));
}
// recombine the individual buckets and sort them
List<Integer> newlist = (bucketList.stream().flatMap(e -> e.stream())
.collect(Collectors.toList()));
Collections.sort(newlist);
return newlist;
}
}
/**
* Debug statements show the start order of the threads is not necessarily the
* finish order.
*
*/
public class BucketSorter
implements Runnable
{
List<Integer> bucket;
public BucketSorter(List<Integer> bucket)
{
this.bucket = bucket;
}
#Override
public void run()
{
System.out.println(
"Thread Launched: " + Thread.currentThread().getName() + ".");
try
{
Thread.sleep(random.longs(400, 2000).findFirst().orElse(200L));
}
catch (InterruptedException e)
{}
System.out.println(
"Thread Done Sleeping: " + Thread.currentThread().getName() + ".");
Collections.sort(bucket);
System.out.println(
"Thread Finished: " + Thread.currentThread().getName() + ".");
}
}
Related
I know I can use callables to get a return value but is it possible to solve this without using it?
I am trying to get the tempCounter value from the primeThread and add them all into the counter. But I received a "symbol not found" error.
Is it possible for me the call the runnable method from the arrayList in the PrimeCounter class?
public class PrimeCounter {
public static void countPrimes() {
int counter = 0;
int primeNumbers = 2_534_111;
final int NUM_OF_THREAD = 4;
int startRange = 2;
int range = primeNumbers / NUM_OF_THREAD;
int endRange = startRange + range;
ArrayList<Thread> threadList = new ArrayList<Thread>();
for (int i = 0; i < NUM_OF_THREAD; i++) {
threadList.add(new Thread(new primeThread(startRange, endRange)));
startRange += range;
if (endRange + range < primeNumbers) {
endRange += range;
} else {
endRange = primeNumbers;
}
}
for (Thread t : threadList) {
t.start();
try {
t.join();
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
}
for (int i = 0; i < threadList.size(); i++) {
Thread tempThread = threadList.get(i);
while (tempThread.isAlive()) {
counter += tempThread.getCounter(); // symbol not found
}
}
System.out.println("\nNumber of identified primes from 2 to " + primeNumbers + " is :" + counter);
}
// checks if n is a prime number. returns true if so, false otherwise
public static boolean isPrime(long n) {
//check if n is a multiple of 2
if (n % 2 == 0) {
return false;
}
//if not, then just check the odds
for (long i = 3; i * i <= n; i += 2) {
if (n % i == 0) {
return false;
}
}
return true;
}
primeThread Runnable
class primeThread implements Runnable {
private int startRange;
private int endRange;
private int threadCounter = 0;
public primeThread(int startRange, int endRange) {
this.startRange = startRange;
this.endRange = endRange;
}
#Override
public void run() {
for (int i = startRange; i < endRange; i++) {
if (Dumb.isPrime(i)) {
threadCounter++;
}
}
}
public int getCounter() {
return threadCounter;
}
First of all read about Java naming convention (your class names did't meet the convention)
With this fragment you say every thread to start, and before next tread to start main thread to wait the termination of this thread(Do you really want this?):
for (Thread t : threadList) {
t.start();
try {
t.join();
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
}
Finally you get a thread from arrayList and you try to run a method that this thread don't have.
for (int i = 0; i < threadList.size(); i++) {
Thread tempThread = threadList.get(i);
while (tempThread.isAlive()) {
counter += tempThread.getCounter(); // symbol not found
}
}
getCounter is method for primeThread class, but you have Thread class!
You can fix this problem if your class primeThread extends Thread class.
I am building a project in which I want to generate several linkedlist in parallel, then merge them and at last want to sort it using multithreading. I have created linkedlists in parallel. Actually I am not sure it is generated sequentially or parallelly. Can anyone help me in solving the problem.
My code is:
public class ParallelMaximizer {
int numThreads;
Random r = new Random();
int Low = 10;
int High = 100;
int numElements = 10;
static ParallelMaximizerWorker[] workers;
public ParallelMaximizer(int numThreads) {
workers = new ParallelMaximizerWorker[numThreads];
}
public static void main(String[] args) {
int numThreads = 4;
ParallelMaximizer maximizer = new ParallelMaximizer(numThreads);
LinkedList<Integer> list = new LinkedList<Integer>();
try {
System.out.println("Maximum Number -> " + maximizer.max(list));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int max(LinkedList<Integer> list) throws InterruptedException {
int max = Integer.MIN_VALUE;
for (int j=0; j<workers.length; j++){
for (int i=0; i<numElements; i++){
int numValues = r.nextInt(High-Low) + Low;
list.add(numValues);
}
System.out.println("LinkedList -> " + list);
for (int i=0; i < workers.length; i++) {
workers[i] = new ParallelMaximizerWorker(list);
workers[i].start();
}
for (int i=0; i<workers.length; i++){
try {
workers[i].join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
list = new LinkedList<>();
}
for(ParallelMaximizerWorker pmw : workers){
max = Math.max(max, pmw.partialMax);
}
return max;
}
}
Other class is:
public class ParallelMaximizerWorker extends Thread {
protected LinkedList<Integer> list;
protected int partialMax = Integer.MIN_VALUE; // initialize to lowest value
public ParallelMaximizerWorker(LinkedList<Integer> list) {
this.list = list;
}
public void run() {
while (true) {
int number;
synchronized(list) {
if (list.isEmpty())
return; // list is empty
number = list.remove();
}
partialMax = Math.max(number, partialMax);
}
}
public int getPartialMax() {
return partialMax;
}
}
I want to generate pairs from a given large pool of numbers. I am using two for loops and threads. My function getAllPairs() in the code generates apairs with a given array of numbers.
I have an array of length 1000. With one thread, output time is nearly 15 sec. Now I want to use 5-6 threads and reduce this output time.I am stuck at dividing this task equally to five threads.If not threads,how to decrease the output time?
Solution with threads is appreciated since I put a lot of time learning multithreading. I would like to implement it.
import java.util.*;
class Pair {
public int x, y;
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public String toString(){
return " ( " + x + " ," + y + " ) " ;
}
}
class selectPairs{
private int[] array;
private List<Pair> totalPairs ;
public selectPairs(int[] arr){
array = arr;
}
//set Method
public void settotalPairs(List<Pair> pieces){
totalPairs = pieces;
}
//get Method
public List<Pair> gettotalPairs(){
return totalPairs;
}
// Method to generate pairs
public List<Pair> getAllPairs() {
List<Pair> pairs = new ArrayList<Pair>();
int total = array.length;
for(int i=0; i < total; i++) {
int num1 = array[i];
for(int j=i+1; j < total; j++) {
int num2 = array[j];
pairs.add(new Pair(num1,num2));
}
}
return pairs;
}
}
// Thread class
class ThreadPairs extends Thread {
private Thread t;
selectPairs SP;
ThreadPairs(selectPairs sp){
SP = sp;
}
public void run() {
synchronized(SP) {
List<Pair> PAIRS = SP.getAllPairs();
SP.settotalPairs(PAIRS);
}
}
}
public class TestThread {
public static void main(String args[]) {
int[] a = new int[1000];
for (int i = 0; i < a.length; i++) {
a[i] = i ;
}
selectPairs ob = new selectPairs(a);
ThreadPairs T = new ThreadPairs( ob );
T.start();
while (true) {
try {
T.join();
break;
}
catch(Exception e){
}
}
List<Pair> Total = new ArrayList<Pair>() ;
List<Pair> Temp1 = ob.gettotalPairs();
Total.addAll(Temp1);
System.out.println(Total);
}
}
A solution with a thread-pool, a task split strategy and it collects all results:
public class SelectPairs {
private static final int NUM_THREADS = 8;
private int[] array;
public SelectPairs(int[] arr) {
array = arr;
}
// A splitting task strategy
public List<Pair> getPartialPairs(int threadIndex, int numThreads) {
List<Pair> pairs = new ArrayList<Pair>();
int total = array.length;
for (int i = threadIndex; i < total; i += numThreads) {
int num1 = array[i];
for (int j = i + 1; j < total; j++) {
int num2 = array[j];
pairs.add(new Pair(num1, num2));
}
}
return pairs;
}
// To use Callables or Runnables are better than extends a Thread.
public static class PartialPairsCall implements Callable<List<Pair>> {
private int thread;
private int totalThreads;
private SelectPairs selectPairs;
public PartialPairsCall(int thread, int totalThreads, SelectPairs selectPairs) {
this.thread = thread;
this.totalThreads = totalThreads;
this.selectPairs = selectPairs;
}
#Override
public List<Pair> call() throws Exception {
return selectPairs.getPartialPairs(thread, totalThreads);
}
}
public static void main(String[] args) throws Exception {
int[] a = new int[1000];
for (int i = 0; i < a.length; i++) {
a[i] = i;
}
SelectPairs sp = new SelectPairs(a);
// Create a thread pool
ExecutorService es = Executors.newFixedThreadPool(NUM_THREADS);
List<Future<List<Pair>>> futures = new ArrayList<>(NUM_THREADS);
// Submit task to every thread:
for (int i = 0; i < NUM_THREADS; i++) {
futures.add(es.submit(new PartialPairsCall(i, NUM_THREADS, sp)));
}
// Collect the results:
List<Pair> result = new ArrayList<>(a.length * (a.length - 1));
for (Future<List<Pair>> future : futures) {
result.addAll(future.get());
}
// Shutdown thread pool
es.shutdown();
System.out.println("result: " + result.size());
}
}
regarding the framework of multithreading, you can implement ThreadPoolExecutor as was suggested in a comment.
Regarding splitting the workload, it seems that the key is splitting the iteration on the array which is achievable if you give the Runnable task a start and end index to iterate over.
We had a lab in Comsci I couldn't figure out. I did a lot of research on this site and others for help but they were over my head. What threw me off were the arrays. Anyway, thanks in advance. I already got my grade, just want to know how to do this :D
PS: I got mean, I just couldn't find the even numbered median and by mode I just gave up.
import java.util.Arrays;
import java.util.Random;
public class TextLab06st
{
public static void main(String args[])
{
System.out.println("\nTextLab06\n");
System.out.print("Enter the quantity of random numbers ===>> ");
int listSize = Expo.enterInt();
System.out.println();
Statistics intList = new Statistics(listSize);
intList.randomize();
intList.computeMean();
intList.computeMedian();
intList.computeMode();
intList.displayStats();
System.out.println();
}
}
class Statistics
{
private int list[]; // the actual array of integers
private int size; // user-entered number of integers in the array
private double mean;
private double median;
private int mode;
public Statistics(int s)
{
size = s;
list = new int[size];
mean = median = mode = 0;
}
public void randomize()
{
Random rand = new Random(12345);
for (int k = 0; k < size; k++)
list[k] = rand.nextInt(31) + 1; // range of 1..31
}
public void computeMean()
{
double total=0;
for (int f = 0; f < size; f++)
{
total = total + list[f];
}
mean = total / size;
}
public void computeMedian()
{
int total2 = 0;
Arrays.sort(list);
if (size / 2 == 1)
{
// total2 =
}
else
{
total2 = size / 2;
median = list[total2];
}
}
public void computeMode()
{
// precondition: The list array has exactly 1 mode.
}
public void displayStats()
{
System.out.println(Arrays.toString(list));
System.out.println();
System.out.println("Mean: " + mean);
System.out.println("Median: " + median);
System.out.println("Mode: " + mode);
}
}
Here are two implementations for your median() and mode() methods:
public void computeMedian() {
Arrays.sort(list);
if ( (list.size & 1) == 0 ) {
// even: take the average of the two middle elements
median = (list[(size/2)-1] + list[(size/2)]) / 2;
} else {
// odd: take the middle element
median = list[size/2];
}
}
public void computeMode() {
// precondition: The list array has exactly 1 mode.
Map<Integer, Integer> values = new HashMap<Integer, Integer>();
for (int i=0; i < list.size; ++i) {
if (values.get(list[i]) == null) {
values.put(list[i], 1);
} else {
values.put(list[i], values.get(list[i])+1);
}
}
int greatestTotal = 0;
// iterate over the Map and find element with greatest occurrence
Iterator it = values.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
if (pair.getValue() > greatestTotal) {
mode = pair.getKey();
greatestTotal = pair.getValue();
}
it.remove();
}
}
The sort method results in a concurrent modification error when i use temp = iterator.next(). Can you please help me resolve the concurrent modification error.
I gave the code for the entire class but I'm only trying complete the sort method. Thanks in advance for your help.
I have to sort all the the arrays in the arraylist.
package HashSet;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ListIterator;
import java.util.Scanner;
public class PhoneBook {
int capacity = 10;
private ArrayList<PhoneBookEntry>[] buckets;
public PhoneBook() {
this(10);
load();
}
public PhoneBook(int size) {
capacity = size;
buckets = new ArrayList[size];
for (int i = 0; i < buckets.length; i++)
buckets[i] = new ArrayList<PhoneBookEntry>();
}
public int getSize() {
int tot = 0;
for (ArrayList<PhoneBookEntry> x : buckets)
tot += x.size();
return tot;
}
public boolean add(PhoneBookEntry entry) {
if (contains(entry))
return false;
int x = Math.abs(entry.hashCode());
buckets[x % buckets.length].add(entry);
return true;
}
public void load() {
InputStream is = getClass().getClassLoader().getResourceAsStream(
"phone.txt");
Scanner scan = new Scanner(is);
while (scan.hasNext())
add(new PhoneBookEntry(scan.next(), scan.nextInt()));
scan.close();
}
public void bucketSize() {
for (int i = 0; i < buckets.length; i++)
System.out.println(i + " " + buckets[i].size());
}
public boolean contains(PhoneBookEntry word) {
int x = Math.abs(word.hashCode());
return buckets[x % buckets.length].contains(word);
}
public int getCapacity() {
return capacity;
}
public int getLongestList() {
int numb = 0;
for (ArrayList<PhoneBookEntry> x : buckets)
if (x.size() > numb)
numb = x.size();
return numb;
}
public void display() {
for (ArrayList<PhoneBookEntry> x : buckets)
System.out.println(x);
}
public int getNumberOfNulls() {
int numb = 0;
for (ArrayList<PhoneBookEntry> x : buckets)
if (x.size() == 0)
numb++;
return numb;
}
public String lookup(String name) {
String numb = name + "'s number not found";
for (ArrayList<PhoneBookEntry> x : buckets)
for (int i = 0; i < x.size(); i++)
if (x.get(i).getN().equals(name))
numb = name + "'s" + " number is " + x.get(i).getNr();
return numb;
}
public int internalLookUp(String name) {
int numb = 0;
for (ArrayList<PhoneBookEntry> x : buckets)
for (int i = 0; i < x.size(); i++)
if (x.get(i).getN().equals(name))
numb = x.get(i).getNr();
return numb;
}
public void sort() {
String temp = "";
ArrayList<String> list = new ArrayList<String>();
ListIterator<String> iterator = list.listIterator();
final ArrayList<PhoneBookEntry>[] data = buckets.clone();
for (ArrayList<PhoneBookEntry> x : buckets) {
for (int i = 0; i < x.size(); i++) {
list.add(x.get(i).getN());
}
Collections.sort(list);
for (int b = 0; b < x.size(); b++) {
temp = iterator.next(); //error line
x.get(b).setN(temp);
x.get(b).setNr(internalLookUp(temp));
}
}
}
public static void main(String[] args) {
PhoneBook phone = new PhoneBook();
phone.display();
System.out.println();
System.out.println("Capacity is " + phone.getCapacity());
System.out.println();
System.out.println("Size is " + phone.getSize());
System.out.println();
System.out.println("Get longest list " + phone.getLongestList());
System.out.println();
System.out.println("Number of Nulls " + phone.getNumberOfNulls());
System.out.println();
System.out.println(phone.lookup("Fish"));
phone.sort();
}
}
It looks like your problem is that you're creating an iterator for a list, then modifying the list (adding + sorting), then attempting to use the iterator.
If you instead created the iterator after this, it should work.
eg.
for (ArrayList<PhoneBookEntry> x : buckets) {
for (int i = 0; i < x.size(); i++) {
list.add(x.get(i).getN());
}
Collections.sort(list);
ListIterator<String> iterator = list.listIterator(); // Iterator created here
for (int b = 0; b < x.size(); b++) {
temp = iterator.next(); //error line
x.get(b).setN(temp);
x.get(b).setNr(internalLookUp(temp));
}
The bug is that you iterate over list while you add to it. you should not do that.
Here is the javadoc for the ConcurrentModificationException.
http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html
if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
As other posters have said, you should do all sorting and adding before or after using your iterator. You can remove an element during iteration, but you must use Iterator.remove() to prevent getting the same exception again.