Java Thread instantiation with incorrect variables - java

I'm trying to use multithreading to break down a large block of processing data into smaller chunks.
The problem I am having is that my threads aren't running against their specified portion of the data space.
For example:
thread-2 should process range of 0 - 1000
thread-3 should process range of 1001 - 2000
When I call my new threads back to back i get:
thread-2 = 0 - 1000
thread-3 = 0 - 1000
When I add a Thread sleep(3000) in between the two thread calls i get:
thread-2 = 0 - 1000
thread-3 = 0 - 2000
I'm not sure what I'm doing wrong and would really appreciate some guidance.
Note on Snippits below, I abbreviated the above numbers actual call range in example below is
1,000,000 - 1,001,000 and 1,001,001 - 1,002,000
Snippet from main method detailing thread call:
try {
int start = 1000000;
int end = 1001000;
new Thread(new MyThread(start, end, PUBLIC_INVALID_LIST)).start();
Thread.sleep(3000);
start = 1001001;
end = 1002000;
new Thread(new MyThread(start, end, PUBLIC_INVALID_LIST)).start();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
Snippet from MyThread which extends Thread
This details how I am passing params from the main method through to the run() method:
//variables to pass from constructor to run()
private int startIndex;
private int endIndex;
private ArrayList PUBLIC_INVALID_LIST;
MyThread(int startIndex, int endIndex, ArrayList PUBLIC_INVALID_LIST) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.PUBLIC_INVALID_LIST = PUBLIC_INVALID_LIST;
}//end of initializer
public void run() {

still not sure what the issue was with the variable pass in, but I got an alternate pass in method to work using int[]
int sizeSet = (max /100000) + 1;//max is highest path_id value
int[] start_range = new int[sizeSet];
int[] end_range = new int[sizeSet];
start_range[0] = 1;//first possible path_id
end_range[0] = 100000;//end point of first possible range
int rangeIndex = 1;//create counter for while loop
while(rangeIndex < sizeSet){
start_range[rangeIndex] = start_range[rangeIndex - 1] + 100000;
end_range[rangeIndex] = end_range[rangeIndex - 1] + 100000;
++ rangeIndex;
}//end range setting while block
rangeIndex = 0;//reset index counter
while(rangeIndex < sizeSet){
new Thread(new MyThread(start_range[rangeIndex], end_range[rangeIndex], PUBLIC_INVALID_LIST)).start();
++ rangeIndex;
}

Related

Finding Maximum in an array; using four threads in Java

I've been trying to write a program to find the max value in an array.
I know how to use threads to find it but to get the right answer I need to use .join ().
I don't get why it wouldn't find the max without using .join (); and if I use .join () then the running time of the program would be as much as the same program without threads; so if it's the only way to run my thread and it doesn't fasten the process why do we use threads?
public void run() {
for (int i = start; i < end; i++) {
if (array[i] > threadMax) {
threadMax = array[i];
}
}
}
This is my run method; I give each thread quarter of the array and then find the max between them.
this works but if only I use .join() but I don't want to slow down the program.
what else can I do?
Edit: This is my code:
ThreadMax[] findMax = new ThreadMax[4];
findMax[0] = new ThreadMax(array, 0,array.length/4);
findMax[1] = new ThreadMax(array, array.length/4, (2*array.length)/4);
findMax[2] = new ThreadMax(array, (2*array.length)/4, (3 * array.length) / 4);
findMax[3] = new ThreadMax(array, (3 * array.length) / 4, array.length);
for(int i = 0; i < 4; i++) {
findMax[i].myThread.start();
try {
findMax[i].myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int[] topFour = new int[4];
for(int i = 0; i < 4; i++)
topFour[i] = findMax[i].threadMax;
int result = 0;
for(int i = 0; i < 4; i++){
if(result < topFour[i])
result = topFour[i];
}
System.out.println("Max = " + result);
and my ThreadMax class:
int start;
int end;
int threadMax;
int[] array;
Thread myThread;
ThreadMax(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
myThread = new Thread(this);
}
#Override
public void run() {
for (int i = start; i < end; i++) {
if (array[i] > threadMax) {
threadMax = array[i];
}
}
}
Why do you use synchronized? You want to run all threads parallel, this avoids it.
You need to join the threads to see when they have finished. The code you call your threads from is another thread that doesn't know when these four threads are done with their work. join() waits for this moment.
this works but if only I use .join()
"works" means you don't have the correct result without join()? Yes because the calling code (that you unfortunately didn't show) probably runs over the thread-starting lines and comes to it's end even before the threads were started.
Edit
Now as more code is available it's clear to me. You execute a loop:
start the first thread
wait for the first thread
start the second thread...
No thread is started until the previous one has finished!
You need separate loops. FIRST start all threads in one loop, THEN wait for them to finish in a second loop.
You should use the Thread.join() method on the main thread. It ensures that wait for the thread until finish it's job. Otherwise main thread can be terminated before your threads are done.
The class could implement comparable<arraylist> and you could use the Collections.max(arrayList) method.

Sum of range multithreading

My program is trying to sum a range with a given number of threads in order to run it in parallel but it seems that with just one threads it runs better than 4 (I have an 8 core CPU). It is my first time working with multithreading in Java so maybe I have a problem in my code that makes it take longer?
My benchmarks(sum of range 0-10000) done for the moment are:
1 thread: 1350 microsecs (average)
2 thread: 1800 microsecs (average)
4 thread: 2400 microsecs (average)
8 thread: 3300 microsecs (average)
Thanks in advance!
/*
Compile: javac RangeSum.java
Execute: java RangeSum nThreads initRange finRange
*/
import java.util.ArrayList;
import java.util.concurrent.*;
public class RangeSum implements Runnable {
private int init;
private int end;
private int id;
static public int out = 0;
Object lock = new Object();
public synchronized static void increment(int partial) {
out = out + partial;
}
public RangeSum(int init,int end) {
this.init = init;
this.end = end;
}//parameters to pass in threads
// the function called for each thread
public void run() {
int partial = 0;
for(int k = this.init; k < this.end; k++)
{
partial = k + partial + 1;
}
increment(partial);
}//thread: sum its id to the out variable
public static void main(String args[]) throws InterruptedException {
final long startTime = System.nanoTime()/1000;//start time: microsecs
//get command line values for
int NumberOfThreads = Integer.valueOf(args[0]);
int initRange = Integer.valueOf(args[1]);
int finRange = Integer.valueOf(args[2]);
//int[] out = new int[NumberOfThreads];
// an array of threads
ArrayList<Thread> Threads = new ArrayList<Thread>(NumberOfThreads);
// spawn the threads / CREATE
for (int i = 0; i < NumberOfThreads; i++) {
int initial = i*finRange/NumberOfThreads;
int end = (i+1)*finRange/NumberOfThreads;
Threads.add(i, new Thread(new RangeSum(initial,end)));
Threads.get(i).start();
}
// wait for the threads to finish / JOIN
for (int i = 0; i < NumberOfThreads; i++) {
try {
Threads.get(i).join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("All threads finished!");
System.out.println("Total range sum: " + out);
final long endTime = System.nanoTime()/1000;//end time
System.out.println("Time elapsed: "+(endTime - startTime));
}
}
Your workload entirely in memory-non-blocking computation - on a general principle, in this kind of scenario, a single thread will complete the work faster than multiple threads.
Multiple threads tend to interfere with the L1/L2 CPU caching and incur additional overhead for context
switching
Specifically, wrt to your code, you initialize final long startTime = System.nanoTime()/1000; too early and measure thread setup time as well as the actual time it takes them to complete. Its probably better to setup your Threads list first and then:
final long startTime =...
for (int i = 0; i < NumberOfThreads; i++) {
Thread.get(i).start()
}
but really, in this case, the expectations that multiple threads will improve processing time is not warranted.

Multithreading only .4 of a second faster?

so for my programming class we have to do the following:
Fill an integer array with 5 million integers ranging from 0-9.
Then find the number of times each number (0-9) occurs and display this.
We have to measure the time it takes to count the occurences for both single threaded, and multi-threaded. Currently I average 9.3ms for single threaded, and 8.9 ms multithreaded with 8 threads on my 8 core cpu, why is this?
Currently for multithreading I have one array filled with numbers and am calculating lower and upper bounds for each thread to count occurences. here is my current attempt:
public void createThreads(int divisionSize) throws InterruptedException {
threads = new Thread[threadCount];
for(int i = 0; i < threads.length; i++) {
final int lower = (i*divisionSize);
final int upper = lower + divisionSize - 1;
threads[i] = new Thread(new Runnable() {
long start, end;
#Override
public void run() {
start = System.nanoTime();
for(int i = lower; i <= upper; i++) {
occurences[numbers[i]]++;
}
end = System.nanoTime();
milliseconds += (end-start)/1000000.0;
}
});
threads[i].start();
threads[i].join();
}
}
Could anyone shed some light? Cheers.
You are essentially doing all the work sequentially because each thread you create you immediately join it.
Move the threads[i].join() outside the main construction loop into it's own loop. While you're at it you should probably also start all of the threads outside of the loop as starting them while new threads are still being created is not a good idea because creating threads takes time.
class ThreadTester {
private final int threadCount;
private final int numberCount;
int[] numbers = new int[5_000_000];
AtomicIntegerArray occurences;
Thread[] threads;
AtomicLong milliseconds = new AtomicLong();
public ThreadTester(int threadCount, int numberCount) {
this.threadCount = threadCount;
this.numberCount = numberCount;
occurences = new AtomicIntegerArray(numberCount);
threads = new Thread[threadCount];
Random r = new Random();
for (int i = 0; i < numbers.length; i++) {
numbers[i] = r.nextInt(numberCount);
}
}
public void createThreads() throws InterruptedException {
final int divisionSize = numbers.length / threadCount;
for (int i = 0; i < threads.length; i++) {
final int lower = (i * divisionSize);
final int upper = lower + divisionSize - 1;
threads[i] = new Thread(new Runnable() {
#Override
public void run() {
long start = System.nanoTime();
for (int i = lower; i <= upper; i++) {
occurences.addAndGet(numbers[i], 1);
}
long end = System.nanoTime();
milliseconds.addAndGet(end - start);
}
});
}
}
private void startThreads() {
for (Thread thread : threads) {
thread.start();
}
}
private void finishThreads() throws InterruptedException {
for (Thread thread : threads) {
thread.join();
}
}
public long test() throws InterruptedException {
createThreads();
startThreads();
finishThreads();
return milliseconds.get();
}
}
public void test() throws InterruptedException {
for (int threads = 1; threads < 50; threads++) {
ThreadTester tester = new ThreadTester(threads, 10);
System.out.println("Threads=" + threads + " ns=" + tester.test());
}
}
Note that even here the fastest solution is using one thread but you can clearly see that an even number of threads does it quicker as I am using an i5 which has 2 cores but works as 4 via hyperthreading.
Interestingly though - as suggested by #biziclop - removing all contention between threads via the occurrences by giving each thread its own `occurrences array we get a more expected result:
The other answers all explored the immediate problems with your code, I'll give you a different angle: one that's about design of multi-threading in general.
The idea of parallel computing speeding up calculations depends on the assumption that the small bits you broke the problem up into can indeed be run in parallel, independently of each other.
And at first glance, your problem is exactly like that, chop the input range up into 8 equal parts, fire up 8 threads and off they go.
There is a catch though:
occurences[numbers[i]]++;
The occurences array is a resource shared by all threads, and therefore you must control access to it to ensure correctness: either by explicit synchronization (which is slow) or something like an AtomicIntegerArray. But the Atomic* classes are only really fast if access to them is rarely contested. And in your case access will be contested a lot, because most of what your inner loop does is incrementing the number of occurrences.
So what can you do?
The problem is caused partly by the fact that occurences is such a small structure (an array with 10 elements only, regardless of input size), threads will continuously try to update the same element. But you can turn that to your advantage: make all the threads keep their own separate tally, and when they all finished, just add up their results. This will add a small, constant overhead to the end of the process but will make the calculations go truly parallel.
The join method allows one thread to wait for the completion of another, so the second thread will start only after the first will finish.
Join each thread after you started all threads.
public void createThreads(int divisionSize) throws InterruptedException {
threads = new Thread[threadCount];
for(int i = 0; i < threads.length; i++) {
final int lower = (i*divisionSize);
final int upper = lower + divisionSize - 1;
threads[i] = new Thread(new Runnable() {
long start, end;
#Override
public void run() {
start = System.nanoTime();
for(int i = lower; i <= upper; i++) {
occurences[numbers[i]]++;
}
end = System.nanoTime();
milliseconds += (end-start)/1000000.0;
}
});
threads[i].start();
}
for(int i = 0; i < threads.length; i++) {
threads[i].join();
}
}
Also there seem to be a race condition in code at occurences[numbers[i]]++
So most probably if you update the code and use more threads the output wouldn't be correct. You should use an AtomicIntegerArray: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicIntegerArray.html
Use an ExecutorService with Callable and invoke all tasks then you can safely aggregate them. Also use TimeUnit for elapsing time manipulations (sleep, joining, waiting, convertion, ...)
Start by defining the task with his input/output :
class Task implements Callable<Task> {
// input
int[] source;
int sliceStart;
int sliceEnd;
// output
int[] occurences = new int[10];
String runner;
long elapsed = 0;
Task(int[] source, int sliceStart, int sliceEnd) {
this.source = source;
this.sliceStart = sliceStart;
this.sliceEnd = sliceEnd;
}
#Override
public Task call() {
runner = Thread.currentThread().getName();
long start = System.nanoTime();
try {
compute();
} finally {
elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
}
return this;
}
void compute() {
for (int i = sliceStart; i < sliceEnd; i++) {
occurences[source[i]]++;
}
}
}
Then let's define some variable to manage parameters:
// Parametters
int size = 5_000_000;
int parallel = Runtime.getRuntime().availableProcessors();
int slices = parallel;
Then generates random input:
// Generated source
int[] source = new int[size];
ThreadLocalRandom random = ThreadLocalRandom.current();
for (int i = 0; i < source.length; i++) source[i] = random.nextInt(10);
Start timing total computation and prepare tasks:
long start = System.nanoTime();
// Prepare tasks
List<Task> tasks = new ArrayList<>(slices);
int sliceSize = source.length / slices;
for (int sliceStart = 0; sliceStart < source.length;) {
int sliceEnd = Math.min(sliceStart + sliceSize, source.length);
Task task = new Task(source, sliceStart, sliceEnd);
tasks.add(task);
sliceStart = sliceEnd;
}
Executes all task on threading configuration (don't forget to shutdown it !):
// Execute tasks
ExecutorService executor = Executors.newFixedThreadPool(parallel);
try {
executor.invokeAll(tasks);
} finally {
executor.shutdown();
}
Then task have been completed, just aggregate data:
// Collect data
int[] occurences = new int[10];
for (Task task : tasks) {
for (int i = 0; i < occurences.length; i++) {
occurences[i] += task.occurences[i];
}
}
Finally you can output computation result:
// Display result
long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
System.out.printf("Computation done in %tT.%<tL%n", calendar(elapsed));
System.out.printf("Results: %s%n", Arrays.toString(occurences));
You can also output partial computations:
// Print debug output
int idxSize = (String.valueOf(size).length() * 4) / 3;
String template = "Slice[%," + idxSize + "d-%," + idxSize + "d] computed in %tT.%<tL by %s: %s%n";
for (Task task : tasks) {
System.out.printf(template, task.sliceStart, task.sliceEnd, calendar(task.elapsed), task.runner, Arrays.toString(task.occurences));
}
Which gives on my workstation:
Computation done in 00:00:00.024
Results: [500159, 500875, 500617, 499785, 500017, 500777, 498394, 498614, 499498, 501264]
Slice[ 0-1 250 000] computed in 00:00:00.013 by pool-1-thread-1: [125339, 125580, 125338, 124888, 124751, 124608, 124463, 124351, 125023, 125659]
Slice[1 250 000-2 500 000] computed in 00:00:00.014 by pool-1-thread-2: [124766, 125423, 125111, 124756, 125201, 125695, 124266, 124405, 125083, 125294]
Slice[2 500 000-3 750 000] computed in 00:00:00.013 by pool-1-thread-3: [124903, 124756, 124934, 125640, 124954, 125452, 124556, 124816, 124737, 125252]
Slice[3 750 000-5 000 000] computed in 00:00:00.014 by pool-1-thread-4: [125151, 125116, 125234, 124501, 125111, 125022, 125109, 125042, 124655, 125059]
the small trick to convert elapsed millis in a stopwatch calendar:
static final TimeZone UTC= TimeZone.getTimeZone("UTC");
public static Calendar calendar(long millis) {
Calendar calendar = Calendar.getInstance(UTC);
calendar.setTimeInMillis(millis);
return calendar;
}

Java-Threads ArrayIndexOutOfBoundsException [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 1 year ago.
I have made a program (for teaching myself purposes) with threads, which is calculating multiplication of elements of an array , using 2 threads. But I get for both threads an ArrayIndexOutOfBoundsException. The error looks like this:
Exception in thread "Thread-1" Exception in thread "Thread-0" Executing multiplying of last2elements
java.lang.ArrayIndexOutOfBoundsException: 1
at FirstPart.run(FirstPart.java:12)
java.lang.ArrayIndexOutOfBoundsException: 1
at SecondPart.run(SecondPart.java:10)
Java Code :
FirstPart.java
public class FirstPart extends Thread {
int multiply = 1;
static int n;
static int[] v = new int[n];
public void run() {
System.out.println("Executing multiplying of first "+MultiplyDemo.cap1+"elements");
for(int i = 1; i <= MultiplyDemo.cap1; i++) {
multiply = multiply * FirstPart.v[i];
System.out.println("Multiplication is "+ multiply);
}
}
}
SecondPart.java:
public class SecondPart extends Thread {
int multiply = 1;
public void run() {
System.out.println("Executing multiplying of last " + (FirstPart.n - MultiplyDemo.cap1) + "elements");
for(int i = MultiplyDemo.cap1;i <= FirstPart.n; i++) {
multiply=multiply*FirstPart.v[i];
System.out.println("Multiplication is "+multiply);
}
}
}
MultiplyDemo.java:
import java.util.Scanner;
import java.util.Vector;
public class MultiplyDemo {
public static int cap1;
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("introduceti numarul de elemente din vector:");
FirstPart.n=s.nextInt();
int []v=new int[FirstPart.n];
System.out.println("Elementele vectorului sunt");
for(int i = 0; i < v.length; i++)
v[i]=s.nextInt();
cap1=FirstPart.n / 2;
FirstPart thread1=new FirstPart();
SecondPart thread2=new SecondPart();
thread1.start();
thread2.start();
try { // wait for completion of all thread and then sum
thread1.join();
thread2.join(); //wait for completion of MathCos object
double z = thread1.multiply + thread2.multiply;
System.out.println("produsul elementelor este" +z);
}
catch(InterruptedException IntExp) {
}
}
}
Arrays indexes are 0-based; if an array has a size of n valid indexes are in range 0..n-1.
All your for loops check with a <= instead of using < and this is why you are getting ArrayIndexOutOfBoundsException.
Usually a "for loop" on arrays has this form:
Object[] array = new Object[size];
for(int i = 0;i < array.length;i++) {
..
}
In this way you can never exceed the size of array
Make your both for loop to this :
for(int i=0; i < MultiplyDemo.cap1; i++)
And PS : Please post question in proper format so that it will be easy for someone to help with.
MultiplyDemo.cap1 is bigger than you n leading to your for loop trying to access an index that does not exist:
for(int i=1;i<=MultiplyDemo.cap1;i++)
multiply=multiply*FirstPart.v[i]; // Misses index 0 and tries to go to index n, when n-1 is max
FirstPart.v is still an empty array. You are assigning the value to n from the main() method and initializing values to a local array which doesn't affect FirstPart.v
Your "n" defaults as 0, and so your v array has 0 length.
This is why you're getting index out of bounds.
In your main method, you're initalizing a new "v" variable. Keep in mind that this "v" array is not the same static "v" array as in "FirstPart"

Shuffling array in multiple threads

I have an array of size N. I want to shuffle its elements in 2 threads (or more). Each thread should work with it's own part of the array.
Lets say, the first thread shuffles elements from 0 to K, and the second thread shuffles elements from K to N (where 0 < K < N). So, it can look like this:
//try-catch stuff is ommited
static void shuffle(int[] array) {
Thread t1 = new ShufflingThread(array, 0, array.length / 2);
Thread t2 = new ShufflingThread(array, array.length / 2, array.length);
t1.start();
t2.start();
t1.join();
t2.join();
}
public static void main(String[] args) {
int array = generateBigSortedArray();
shuffle(array);
}
Are there any guaranties from JVM that I will see changes in the array from the main method after such shuffling?
How should I implement ShufflingThread (or, how should I run it, maybe within a synchronized block or whatever else) in order to get such guaranties?
The join() calls are sufficient to ensure memory coherency: when t1.join() returns, the main thread "sees" whatever operations thread t1 did on the array.
Also, Java guarantees that there is no word-tearing on arrays: distinct threads may use distinct elements of the same array without needing synchronization.
I think this is a good exercise in thread control, where (1) a job can be broken up into several parts (2) the parts can run independently and asynchronously and (3) A master thread monitors the completion of all such jobs in their respective threads. All you need is for this master thread to wait() and be notify()-ed jobCount times, every time a thread completes execution. Here is a sample code that you can compile/run. Uncomment the println()'s to see more.
Notes: [1] JVM doesnt guarantee the order of execution of the threads [2] You need to synchronize when your master thread access the big array, to not have corrupted data....
public class ShufflingArray {
private int nPart = 4, // Count of jobs distributed, resource dependent
activeThreadCount, // Currently active, monitored with notify
iRay[]; // Array the threads will work on
public ShufflingArray (int[] a) {
iRay = a;
printArray (a);
}
private void printArray (int[] ia) {
for (int i = 0 ; i < ia.length ; i++)
System.out.print (" " + ((ia[i] < 10) ? " " : "") + ia[i]);
System.out.println();
}
public void shuffle () {
int startNext = 0, pLen = iRay.length / nPart; // make a bunch of parts
for (int i = 0 ; i < nPart ; i++, activeThreadCount++) {
int start = (i == 0) ? 0 : startNext,
stop = start + pLen;
startNext = stop;
if (i == (nPart-1))
stop = iRay.length;
new Thread (new ShuffleOnePart (start, stop, (i+1))).start();
}
waitOnShufflers (0); // returns when activeThreadCount == 0
printArray (iRay);
}
synchronized private void waitOnShufflers (int bump) {
if (bump == 0) {
while (activeThreadCount > 0) {
// System.out.println ("Waiting on " + activeThreadCount + " threads");
try {
wait();
} catch (InterruptedException intex) {
}}} else {
activeThreadCount += bump;
notify();
}}
public class ShuffleOnePart implements Runnable {
private int startIndex, stopIndex; // Operate on global array iRay
public ShuffleOnePart (int i, int j, int k) {
startIndex = i;
stopIndex = j;
// System.out.println ("Shuffler part #" + k);
}
// Suppose shuffling means interchanging the first and last pairs
public void run () {
int tmp = iRay[startIndex+1];
iRay[startIndex+1] = iRay[startIndex]; iRay[startIndex] = tmp;
tmp = iRay[stopIndex-1];
iRay[stopIndex-1] = iRay[stopIndex-2]; iRay[stopIndex-2] = tmp;
try { // Lets imagine it needs to do something else too
Thread.sleep (157);
} catch (InterruptedException iex) { }
waitOnShufflers (-1);
}}
public static void main (String[] args) {
int n = 25, ia[] = new int[n];
for (int i = 0 ; i < n ; i++)
ia[i] = i+1;
new ShufflingArray(ia).shuffle();
}}
Thread.start() and Thread.join() are enough to give you the happens-before relationships between the array initialisation, its hand-off to the threads and then the read back in the main method.
Actions that cause happens-before are documented here.
As mentioned elsewhere, ForkJoin is very well suited to this kind of divide-and-conquer algorithm and frees you from a lot of the book-keeping that you'd otherwise need to implement.
using ExecutorService from java.util.Concurrent package along with Callable Task to return the part of the array's from each thread run, once both thread are completed is another way to do for consistent behaviour.
Well, they can't BOTH be accessing the same array and if you use a lock, or a mutex or any other synchronizing mechanism, you kinda lose the power of the threads (since one will have to wait for another, either to finish the shuffling or finish a bit of the shuffling).
Why don't you just divide the array in half, give each thread its bit of the array and then merge the two arrays?

Categories