The task is to find max and min values in a MxN matrix, and do it "in parallel" using Java Threads.
I was pretty surprised to find out that my parallelSearch() method runs much slower compared to the regularSearch() method. Both of them use the same brute-force algorithm, so even though you can probably solve this problem using a better algorithm, both methods should be on the even playing field.
I'm curious to find out why: is it because creating new Thread objects is a time-expensive task, or is it because I'm doing something totally wrong in my parallelSearch() method?
import java.util.Random;
public class Task {
static int max = -1;
static int min = 99;
static int[][] matrix;
static Random rnd = new Random();
static{
matrix = new int[4][1000];
Task t = new Task();
t.fill(matrix);
}
public static void main(String[] args) throws InterruptedException {
Task t = new Task();
long cur = System.currentTimeMillis();
System.out.println(t.regularSearch(matrix));
System.out.println("regular search took "+(System.currentTimeMillis() - cur)+" millis ");
cur = System.currentTimeMillis();
System.out.println(t.parallelSearch(matrix));
System.out.println("parallel search took "+(System.currentTimeMillis() - cur)+" millis ");
}
void fill(int[][] input){
for (int i = 0; i < input.length; i++) {
for (int i1 = 0; i1 < input[i].length; i1++) {
input[i][i1] = rnd.nextInt(200);
}
}
}
String regularSearch(int[][]input){
StringBuilder result = new StringBuilder();
for (int[] anInput : input) {
for (int anAnInput : anInput) {
if(anAnInput>max){
max = anAnInput;
}
if(anAnInput<min){
min = anAnInput;
}
}
}
String rslt = result.append("max: ").append(max).append(" min: ").append(min).toString();
max = -1;
min = 200; //doing this to have a fair comparison in main()
return rslt;
}
String parallelSearch(int[][] input) throws InterruptedException {
StringBuilder result = new StringBuilder();
for (int i = 0; i < input[0].length; i++) {
int x = i;
Thread t = new Thread(()->{
for (int[] anInput : input) {
if (anInput[x] > max) {
max = anInput[x];
}
if (anInput[x] < min) {
min = anInput[x];
}
}
});
t.start();
}
Thread.sleep(10);
result.append("max: ").append(max).append(" min: ").append(min);
return result.toString();
}
}
EDIT:
As was pointed out in the comments, my parallelSearch() was creating way more Threads than necessary, and I've rewritten it to better suit my task. This one actually runs faster than the regular one on big sizes. I've tested it against a 4x500000 matrix with random.nextInt(100000) bound and it runs as fast or even up to 10 seconds faster then the regularSearch()
String parallelSearch(int[][] input) throws InterruptedException {
StringBuilder result = new StringBuilder();
for (int i = 0; i < input.length; i++) {
int x = i;
Thread t = new Thread(()->{
for(int num:input[x]){
if(num>max){
max = num;
}
if(num<min){
min = num;
}
}
});
t.start();
}
Thread.sleep(10);
result.append("max: ").append(max).append(" min: ").append(min);
return result.toString();
}
Related
I'm learning to use threads in java, since I want to speed up a task to reduce time. I try to see how long it takes to finish the threads but since I don't know how to use join in this case:
public class MyThread1 extends Thread {
int inicio;
int fin;
public MyThread1(int _inicio, int _fin) {
this.inicio = _inicio;
this.fin = _fin;
}
#Override
public void run() {
String pass;
for(int i = inicio; i < fin; i++){
pass = Integer.toString(i);
System.out.println(pass);
}
}
}
public static void main(String arg[]) throws UnknownHostException {
long previousTime;
previousTime = System.currentTimeMillis();
int threads = 10; // Number of threads
for (int i = 0; i < threads; i++) {
MyThread1 object = new MyThread1(0,10);
object.start();
}
long currentTime = System.currentTimeMillis();
double elapsedTime = (currentTime - previousTime) / 1000.0;
System.out.println("Time in seconds : " + String.valueOf(elapsedTime));
}
Add MyThread1 object to an array that is declared before the loop. After the loop, have another loop which will join on all objects.
for (int i = 0; i < threads; i++) {
MyThread1 object = new MyThread1(0,10);
arr[i] = object;
object.start();
}
for (int i = 0; i < threads; i++) {
arr[i].join();
}
I'm making a basic program for my computer science class, which is supposed to perform a selection sort on an array.
Problem is, it stops in the middle of the process and I can't figure out why.
It used to give me an out of bound exception, which it for some reason doesn't do anymore.
I'd appreciate if someone could help me fix it.
import java.util.Random;
public class main {
public static void main(String[] args) {
int i;
int j;
int k;
int tausch;
//int size = 10;
Random rand = new Random();
int z[] = new int[10];
for(i=0;i<10;i++) {
z[i] = rand.nextInt(10) + 1;
}
for(i=0;i<z.length;i++) {
System.out.print(z[i]+", ");
}
long startTime = System.nanoTime();
for(i=0;i<z.length;i++) {
k = i;
for(j=i+1;j<10;i++) {
if(z[k] > z[j]) {
k = j;
}
}
tausch = z[i];
z [i] = z[k];
z[k] = tausch;
}
long endTime = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println();
for(i=0;i<z.length;i++) {
System.out.print(z[i]+", ");
}
System.out.println();
System.out.print(totalTime);
}
}
for(j=i+1;j<10;i++)
Should be for(j=i+1;j<10;j++) - you're incrementing the wrong variable.
I will input some number to calculates sum of Factorial series,
like if i put 5, output will be 1!+2!+3!+4!+5!, but calculating processing could be heavy so i want to use multiple treads that calculates each factorial.. means thread1 cals 1!, thread2 cals 2!...
i used arrays of threads but can't sync them in propel results. and can't find the way to sum these results.
i wrote codes...
public class Calthread extends Thread{
private int num=1;
public Calthread(int num) {
this.num = num;
}
public void run() {
int dft = 1;
for(int i=1; i<=num; i++) {
dft = dft*i;
}
System.out.println(num + "! result :" + dft);
}
}
this is for 1 thread
for main class
public class calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("input number>>");
int k = scanner.nextInt(); //input 'k'
int sum = 0;
Calthread[] cal = new Calthread[k]; // make threads number of 'k'
for(int i = 0; i<k; i++) {
cal[i] = new Calthread(i+1);
cal[i].start();
}
}
}
how can I Sync them and print the sum of all?
To return value from thread you should use Callable instead of Runnable:
public class Calthread implements Callable<Integer> {
private int num = 1;
public Calthread(int num) {
this.num = num;
}
#Override
public Integer call() {
int dft = 1;
for (int i = 1; i <= num; i++) {
dft = dft * i;
}
return dft;
}
}
And in the main class:
public class Calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("input number>>");
int k = scanner.nextInt(); //input 'k'
int sum = 0;
// Make threads number of 'k'. Here we use List instead of array because there is such contract in ExecutorService
List<Calthread> cal = new ArrayList<>(k);
// Create thread pool with fixed number of threads
ExecutorService service = Executors.newFixedThreadPool(k);
// Add all Callable task in one collection
for (int i = 0; i < k; i++) {
cal.add(new Calthread(i+1));
}
try {
// Invoke all Callable task and get List with results
List<Future<Integer>> results = service.invokeAll(cal);
// Future::get is blocking method. It waits result.
for (Future<Integer> result : results) {
sum += result.get();
}
} catch (InterruptedException | ExecutionException e) {
System.out.println("Something went wrong");
e.printStackTrace();
}
System.out.println("Result: " + sum);
// We need to shutdown our service
service.shutdown();
}
}
I am trying to understand ExecutorService and i want to do the sum of all the elements of an array. I did two methods, one that makes the sum serially (just a for loop that sums all the elements) and other concurrently with a pool. My problem is that the total sum from using ExecutorService is off with the serial sum almost all the time, sometimes even just by one.
package sumArregloConc;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class SumaArregloMain {
private final static int cantElem = 1000;
private static ExecutorService tpool = Executors.newCachedThreadPool();
public static void main(String[] args)
{
int[] arreglo = generarArreglo(cantElem); //generate the array with random numbers
System.out.println(sumaSerial(arreglo));
System.out.println(sumaConcurrente(arreglo));
}
public static int sumaSerial(int[] arreglo)
{
int suma = 0;
for(int i =0; i< arreglo.length; i++)
{
suma += arreglo[i];
}
return suma;
}
public static int sumaConcurrente(int[] arreglo)
{
AtomicInteger total = new AtomicInteger(0);
for(int i = 1 ; i < cantElem; i++){
int a = arreglo[i];
Thread thread = new Thread(new Runnable(){
public void run() {
int res = a;
total.addAndGet(res);
return;
}});
tpool.submit(thread);
}
tpool.shutdown(); //wait for everything to finish
return total.get();
}
public static int[] generarArreglo(int cantElem)
{
int[] arreglo = new int[cantElem];
Random rand = new Random();
for(int i = 0; i < cantElem; i++)
{
arreglo[i] = rand.nextInt(10);
}
return arreglo;
}
}
Can someone tell what is wrong?
Found the error. First what Eric said about awaitTermination and Runnable, but the main bug was just that the loop started at i = 1 instead of i = 0, silly mistake.
public static int sumaConcurrente(int[] arreglo)
{
AtomicInteger total = new AtomicInteger(0);
for(int i = 0 ; i < cantElem; i++){
int a = arreglo[i];
tpool.submit(new Runnable(){
public void run() {
total.addAndGet(a);
return;
}
});
}
tpool.shutdown(); //wait for everything to finish
try {
tpool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
}
return total.get();
}
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.