Multithreaded merge sort Stack Overflow error - multithreading

I'm trying to make a multithreaded merge sort and I've encountered a stack overflow error and I'm not sure what is causing it.
public static void concurrentMergeSort(int[] arr, int threadCount) {
if(threadCount <= 1){
regularMergeSort(arr);
return;
}
int middle = arr.length/2;
int[] left = Arrays.copyOfRange(arr, 0, middle); //Says error here
int[] right = Arrays.copyOfRange(arr, middle, arr.length);
concurrentMergeSort(left);//Says error here
concurrentMergeSort(right);
Thread leftSort = new Thread(new Sorting(left, threadCount));
Thread rightSort = new Thread(new Sorting(right, threadCount));
try{
leftSort.join();
rightSort.join();
}
catch (Exception ex){
ex.printStackTrace();
}
merge(arr, left, right);
}
public static void regularMergeSort(int[] arr){
if(arr.length == 1){
return;
}
int middle = arr.length/2;
int[] left = Arrays.copyOfRange(arr, 0, middle);
int[] right = Arrays.copyOfRange(arr, middle, arr.length);
regularMergeSort(left);
regularMergeSort(right);
merge(arr, left, right);
}
}
I was thinking that maybe it was the thread count never decreasing, but when I modify the thread count I still get the same result. Also it was working until I added a regular merge sort and concurrent merge sort to separate it. I only added the regular merge sort as well because I was barely getting a speed increase from just having the concurrent merge sort method and the main purpose of this modification of merge sort is to increase the time it takes to sort with multithreading.

Your return condition from regularMergeSort is:
if(arr.length == 1)
When middle = 0, you will end up creating an empty array; and this terminating condition won't be hit, and there will be infinite loop. Change this condition to:
if(arr.length <= 1)
And assuming your merge function handles empty arrays, you should be good.

Related

Barrier thread synchronisation in pairs

I want to implement a function that blocks incoming threads until 2 threads of the same colour meet. Each thread is modelled by a unique id and colour. The function should return the id of the other thread it is matched to. I tried to use the idea for rendezvous and barrier to solve the question, which worked when there are only 2 threads at any one time, but when there are more than 2 threads, the id returned is incorrect. I am trying to solve for 1 colour first as the other 2 colors would have similar logic, but I am not sure what I need to change?
int pack_thread(int colour, int id) {
if (colour == 1) {
sem_wait(&d); map[0][count[0]] = id; count[0]++;
if (count[0] == 1) {
sem_post(&d);
sem_post(&a1); sem_wait(&a2); sem_post(&barr);
return map[0][1];
} else if (count[0] == 2) {
sem_post(&d);
sem_wait(&a1); sem_post(&a2);
return map[0][0];
} else {
sem_post(&d);
sem_wait(&barr);
map[0][1] = id;
count[0] = 0;
sem_post(&a2);sem_wait(&a1);
return map[0][0];
}
} else {
return 0;
}

how to prevent reading when hazelcast map is locked

for there are lots of data should be put into hazelcast map, I want to prevent reading from others when the data is putting into the map.
is there any way to realize it?
for example:
map a = map(1,000,000,000) // a has 1,000,000,000 elements
map b = map(2,000) // b has 200 emlemnts
i want to put all of b into a ;
the elements of b should be accessed after all of these are put into map a;
if the elements of map b haven't been put into map a entirely, the elements of map b couldn't be accessed.
use case:
map a ={1,2,3,4,5}
map b ={a,b,c,d,e}
print a // result {1,2,3,4,5}
foreach item in b
a.put item
print a // result {1,2,3,4,5}
end foreach
print a //result {1,2,3,4,5,a,b,c,d,e}
i want to merge these two maps.while, map b's elements couldn't be accessed via map a before merging finished.
my solutions
thank all the people for their help.
after reading the hazelcast manual, I choose the transactionalMap to resolve this problem.
transactionalMap is READ_COMMITED islate. it could suspend reading map(1) threads when the transaction is updating map(1).
``` java
static Runnable tx = new Runnable() {
#Override
public void run() {
try {
logger.info("start transaction...");
TransactionContext txCxt = hz.newTransactionContext();
txCxt.beginTransaction();
TransactionalMap<Object, Object> map = txCxt.getMap("map");
try {
logger.info("before put map(1)");
Thread.sleep(300);
map.put("1", "1"); // reader1 is blocked
logger.info("after put map(1)");
Thread.sleep(500);
map.put("2", "2"); // reader2 is blocked
logger.info("after put map(2)");
Thread.sleep(500);
txCxt.commitTransaction();
logger.info("transaction committed");
} catch (RuntimeException t) {
txCxt.rollbackTransaction();
throw t;
}
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
logger.info("Finished testmap size:{}, testmap(1):{}, testmap(2):{} ", testmap.size(), testmap.get("1"),
testmap.get("2"));
Hazelcast.shutdownAll();
logger.info("system exit.");
System.exit(0);
}
}
};
```
What's your motivation / use-case? You can use transactions, but that could have a bad impact on performance. Alternatively you could use manual locking - see ILock.
However both these techniques should be used as a last-resort - when you have no chance to design your application differently.
One way to achieve this is by locking the segments in Map b while adding to it. Once pushing the entries to Map a is complete, you can unlock the segments.
There will be performance implications with this methods though as it requires an extra step of locking/unlocking.

JavaFX: Platform.runLater(task) not recognized for task = new FutureTask<>(new Runnable() {....}?

Over the last two weeks I have studied 10 different ways to avoid problems with sleep(). The concept of running a block of code on the UI Thread that cannot be interrupted seems the most practical. So I have proceeded to create a FutureTask<Void> object that contains the code not to be interrupted before completed. The code in for loops, pixelArray[r][c].setFill(color) sets the new colors for Circle Objects in a Grid Array that's 32x64. This has always failed to display the colors when just sleep(5000) is invoked between the pixel art files, FileChooser selects and assigns to List<File> selectedFiles. Unfortunately the following code will not compile because runLater in the linePlatform.runLater(diplayFileTask); can't be resolved in the following code:
public class PlayPlaylist{
public static List<File> selectedFiles;
public static void play() throws ExecutionException {
FileChooser fileChooser = new FileChooser();
fileChooser.setInitialDirectory(new File("C:\\ProgramData\\L1 Art Files\\"));
fileChooser.setTitle("Play One or More Pixel Art Files");
List<File> selectedFiles = fileChooser.showOpenMultipleDialog(null);
for (File selectedFile : selectedFiles) {
try {
displayFile(selectedFile.getPath());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
public static void displayFile( String pathName) throws IOException, InterruptedException, ExecutionException {
FutureTask<Void> displayFileTask = new FutureTask<>(new Runnable() {
#Override
public void run() {
path = Paths.get(pathName);
try {
pixelByteArray = Files.readAllBytes(path);
} catch (IOException e) {
e.printStackTrace();
}
int cnt = 0;
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
//int i = r * col + c;
//System.out.println("\nr = " + r + " c = " + c);
String hexRGB = String.format("#%02X%02X%02X",
pixelByteArray[cnt++], //red
pixelByteArray[cnt++], //green
pixelByteArray[cnt++]); //blue
Color color = Color.valueOf(hexRGB);
//System.out.println("\ncolor is " + color);
pixelArray[r][c].setFill(color);
}
}
String fileName = path.getFileName().toString();
window.setTitle(MessageFormat.format("Pixel Array {0} x {1} File: {2}", Integer.toString(row), Integer.toString(col), fileName));
}
}, null); // displayFile
Platform.runLater(displayFileTask);
displayFileTask.get();
sleep(5000);
}
I've followed the example(s) closely in Stack Overflow and fail to see the problem(s).
I have more details on past attempts posted on Stack Overflow at: Wait() & Sleep() Not Working As Thought.
I also have the two UI windows posted on the web at: Virtual Art. I think the pixel art shown in the Pixel Array window clarifies the goal of creating a user-defined slide show.
Can anyone correct my errors? Do you think my sleep(5000) is in the best location?
Answering James_D's questions. This is my best solution to your answer at my first post, Wait() & Sleep() Not Working As Thought. I was actually following your logic and code posted at, java thread immediately update UI.
I save and display pixel art files that are 32x64. You can see an example posted on the Virtual Art website. I thought it would be straight forward to create a slide show under Playlist, click Play. I would use the same class and OpenFile(pathname) method in a for loop to display each file selected and placed in the ArrayList<> but pause by putting Thread.sleep(5000) in the loop.
As you pointed out, this doesn't work, as I best understand, because the Thread.sleep(5000) interrupts the UI Thread causing a "skip" over of just the display code of all the files looped through. But last pixel art file will appear after 5 secs.
I thought your answer in the post referenced above applied: You create a block of code using FutureTask<Void> and Platform.runLater<task> that can't be interrupted until completed. I thought the FutureTask<Void> runs on the UI Thread and would finish displaying the pixel art file before Thread.sleep(5000) could interrupt.
At 68 and retired, I'm new to JavaFX and trying to develop this RGB LED product that can be programmed with a basic pixel editor. Learning JavaFX is a real challenge for me, thanks for your time and patience.

In thread, when loop too much times, Invoke waste a lot of time

for (int i = 0; i < 100,000; i++)
{
threadEvent.Invoke(i, new EventArgs());// tell processbar value
}
threadEvent += new EventHandler(method_threadEvent);
void method_threadEvent(object sender, EventArgs e)
{
int nowValue = Convert.ToInt32(sender);
nowValueDelegate now = new nowValueDelegate(setNow);
this.Invoke(now, nowValue);
}
private void setNow(int nowValue)
{
this.progressBar1.Value = nowValue;
}
private delegate void nowValueDelegate(int nowValue);
in the loop i do nothing, but it also waste alot of time !
why threadEvent.Invoke spend so much time ?
Invoking is an expensive operation, because it has to cross thread boundaries.
It's best to reduce the amount of invokes, by for instance only updating the progress bar for each percentage of work you do, rather than for each iteration of the loop. That way, only 100 updates need to be processed, rather than one for each iteration.
First thing you need to do is to calculate or estimate the current progress.
For a typical loop
for (int i = 0; i < someValue; ++i)
{
... // Work here
}
A good estimate of progress is (i / someValue) * 100, which gives the percentage of the loop that has been completed. To update the progress to the UI thread only when the next percentage has been reached you could do something in the line of:
int percentCompleted = 0;
threadEvent.Invoke(percentCompleted, new EventArgs()); // Initial progressbar value
for (int i = 0; i < someValue; ++i)
{
int newlyCompleted = (i / someValue) * 100;
if (newlyCompleted > percentCompleted)
threadEvent.Invoke(percentCompleted, new EventArgs());
percentCompleted = newlyCompleted;
... // Work here
}
Now finally, you could use BeginInvoke instead of Invoke to make sure the worker thread doesn't wait for the threadEvent to complete (PostMessage behaviour). This works well here because there is no return value from threadEvent that you need.

ObservableList producing errors

I made this program that produces 6 random numbers between 1 and 41. In the UI i have 6 textfields and a button. If i press the button the 6 numbers are being displayed in the textfields. I have 1 function(theNumbers()) fired when the button is pressed, the first function makes an ObservableList with the numbers 1-41 and the second function picks 6 numbers randomly.
The problem that happens is that after pressing the button a few times there is an ArrayIndexOutofBound Exception: -1 thrown, usually after (or a few times after) the number 0 is produced (which isnt even in the list) also sometimes a IndexOutOfBoundsException: Index: 4, Size: 4 exception is thrown(the number is random btw). Also it seems to be able to produce the same number twice or numbers bigger then 41.(seen 151)
This is my code:
First function:
ObservableList<Integer> list1 = FXCollections.observableArrayList();
private void createList(ObservableList<Integer> list1) {
this.list1 = list1;
int numbers = 41;
for (int i = 1; i <= numbers; i++) {
list1.add(i);
}
}
Second function:
private void theNumbers() {
createList(list1);
ObservableList<Integer> finalNums = FXCollections.observableArrayList();
try {
for (int i = 0; i < 6; i++) {
FXCollections.shuffle(list1);
int lucky = new Random().nextInt(list1.size());
finalNums.add(lucky);
list1.remove(list1.indexOf(lucky));
}
} catch (Exception ex) {
throw ex;
}
FXCollections.sort(finalNums);
textField1.setText(finalNums.get(0).toString());
textField2.setText(finalNums.get(1).toString());
textField3.setText(finalNums.get(2).toString());
textField4.setText(finalNums.get(3).toString());
textField5.setText(finalNums.get(4).toString());
textField6.setText(finalNums.get(5).toString());
list1.clear();
finalNums.clear();
}
Any clues to why it does this? Could it be my Acer Aspire One Netbook messing up? To my knowledge these errors shouldn't be happening.
Your code tries to remove the exact same number twice ore more in one pass of the for construct. For example you cannot remove the number "2" more than once from the list. The indexOf(2) method will return with -1 because it cannot find the value 2 in the list anymore.
So you might check if a number still exists in list1 before you try to remove from there.
private void theNumbers() {
createList(list1);
ObservableList<Integer> finalNums = FXCollections.observableArrayList();
try {
for (int i = 0; i < 6; i++) {
FXCollections.shuffle(list1);
int lucky;
do
{
lucky= new Random().nextInt(list1.size());
}while(list1.indexOf(lucky) == -1);
finalNums.add(lucky);
list1.remove(list1.indexOf(lucky));
}
} catch (Exception ex) {
throw ex;
}
That should solve your problem.
try using
int lucky = new Random().nextInt(list1.size()-1);

Resources