Concurrency Multithreading

  • (2 Pages)
  • +
  • 1
  • 2

27 Replies - 1580 Views - Last Post: 26 April 2019 - 02:07 PM Rate Topic: -----

#1 overwhelmed_student   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 63
  • Joined: 10-May 18

Concurrency Multithreading

Posted 26 April 2019 - 05:37 AM

Hi guys,

I am trying to understand concurrency aka having two or more threads run parallel. (Already wrong?)
I was thinking about an example that might help me:
Let's say I have an array filled with numbers 0 to 9. I want to increment all numbers by 1. The array should be 1 to 10.
I tried to do that but whenever I use 2 or more threads, the numbers get incremented by each thread so the result is like 3 to 13. I thought I could divide the array so that each thread works on a separate part but how do I do that? For big sizes that would be the solution to make it faster, right?
(I could implement specific threads to a specific array-size but that can't be the solution. The threads shouldn't have to know the exact size of the array, right?)

Also, is concurrency used for example for loading areas in games? The more threads you can run, the faster everything is loading (like a picture or if you go into a new dungeon)?

Here is my example code that I most recently used. I tried to do it with a threadpool but it didn't work either:

public class ThreadPlay {

    private static int[] array = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};

    private static void printArray(int[] array) {
            for (int i = 0; i < array.length; i++) {
                    array[i] = array[i]+1;
            }
    }

    public static void main(String[] args) {
        
        int threadNo = 1;
        System.out.println("Running on " + threadNo + " threads.");
        Runnable task = () -> printArray(array);
        ExecutorService threadPool = Executors.newFixedThreadPool(threadNo);
        double start = System.currentTimeMillis();

        for(int i = 1; i <= threadNo; i++) {
            threadPool.submit(task);
        }

        double stop = System.currentTimeMillis();
        threadPool.shutdown();
        System.out.println("Time: " + (stop - start) + "ms");

        for(int i = 0; i < array.length; i++) {
            System.out.println(array[i] + " ");
        }
    }
}



I added the time to see if it works faster once the program does what I want it to do. Once I figure out concurrency, I will use a much bigger array to see how many threads my laptop likes the most.

Is This A Good Question/Topic? 0
  • +

Replies To: Concurrency Multithreading

#2 Larry71   User is offline

  • D.I.C Head

Reputation: 7
  • View blog
  • Posts: 66
  • Joined: 05-June 12

Re: Concurrency Multithreading

Posted 26 April 2019 - 05:55 AM

I have implemented this by "dividing" the arrayList in let's say, 4 parts. Actually you don't have to divide it, but set start and end position for each thread.

Make a new method incrementInteger(int start, int end) where start and end are the beginning and end of the part and assign a method for each thread.
What I don't know is if all threads may update this list or extract the results to a new list.

This post has been edited by Larry71: 26 April 2019 - 05:56 AM

Was This Post Helpful? 1
  • +
  • -

#3 overwhelmed_student   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 63
  • Joined: 10-May 18

Re: Concurrency Multithreading

Posted 26 April 2019 - 06:02 AM

View PostLarry71, on 26 April 2019 - 05:55 AM, said:

Make a new method incrementInteger(int start, int end) where start and end are the beginning and end of the part and assign a method for each thread.


I was thinking of doing that. I just thought there is a way, that if I have a program with an array of 100 000 values, I could do it with 2 threads and next time with 4 threads without having to change the code itself. Right now I can't think of one. But then again, I am still a beginner so maybe changing the amount of threads never has to be done.
Was This Post Helpful? 0
  • +
  • -

#4 Larry71   User is offline

  • D.I.C Head

Reputation: 7
  • View blog
  • Posts: 66
  • Joined: 05-June 12

Re: Concurrency Multithreading

Posted 26 April 2019 - 06:10 AM

You should use so many threads, that your processor allows to use parallel. For my i3, I may use only 4.

I had an arrayList of 15 mil. objects and by using 4 threads, time was decreased by 75%.

But read that too...

https://stackoverflo...problem-in-java

This post has been edited by Larry71: 26 April 2019 - 06:16 AM

Was This Post Helpful? 2
  • +
  • -

#5 overwhelmed_student   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 63
  • Joined: 10-May 18

Re: Concurrency Multithreading

Posted 26 April 2019 - 07:04 AM

View PostLarry71, on 26 April 2019 - 06:10 AM, said:

I had an arrayList of 15 mil. objects and by using 4 threads, time was decreased by 75%.


So, I tried dividing my array and it works, but it is not faster than before. I used a for-loop to create the threads:
       for(int i = 1; i <= threadNo; i++) {
            Thread t = new Thread(new ThreadPlay());
            t.run();
            start = end;
            end = end+(array.length/threadNo);
        }



I thought since the main-thread just keeps going after creating a new thread, it would create as many threads as my number is and therefore starting them all but apparently, it doesn't make it faster.
Was This Post Helpful? 0
  • +
  • -

#6 xclite   User is offline

  • I wrote you an code
  • member icon


Reputation: 1380
  • View blog
  • Posts: 4,206
  • Joined: 12-May 09

Re: Concurrency Multithreading

Posted 26 April 2019 - 07:16 AM

There's a lot of overhead in managing threads. As Larry said, you'll see an increase on data sizes large enough that the overhead of creating and tearing down threads is overcome by the savings of doing things in parallel.

On the topic of number of threads, Larry also hinted at something interesting: if your work is CPU-bound, there's not much point in exceeding the physical parallelism of your hardware. Swapping between threads to do the same work on the CPU would be slower than a smaller number of threads that don't have to swap. i.e. if I have 2 cores, 4 threads have to share, but 2 threads can just churn through (ignoring other demands on the operating system).

When it comes to io-bound work, there is much more advantage to pumping the thread count through the roof. If you're waiting for things like a network response, file io, etc, handing the CPU off to another thread can actually be beneficial.

This is an oversimplification, of course. Do you think your work is CPU-bound, or IO-bound?
Was This Post Helpful? 1
  • +
  • -

#7 xclite   User is offline

  • I wrote you an code
  • member icon


Reputation: 1380
  • View blog
  • Posts: 4,206
  • Joined: 12-May 09

Re: Concurrency Multithreading

Posted 26 April 2019 - 07:24 AM

View PostLarry71, on 26 April 2019 - 08:55 AM, said:

What I don't know is if all threads may update this list or extract the results to a new list.



This is a great insight. TECHNICALLY this code needs a little help to be correct, but it's not obvious. Depending on what mode the JVM starts up in, the behavior of memory changes. This is an implementation detail in the JVM memory model that, in some cases, will make this code run "correctly", even if the code itself isn't correct.

The tiny bug is this: threads may or may not "publish" their changes across a memory barrier. In other words, the updates that your threads do this array will be visible by your main thread in some cases, but not all.

In most cases where you're doing shared memory, you need to use some sort of concurrency primitives to protect access. These usually do things like make sure no thread writes at the same time, and that updates are ordered correctly, etc. The basic example of this is the synchronized keyword, though other locking structures exist.

In this case, since none of the writes actually depend on other writes, you can get away with it by applying one small change: make your array volatile.

volatile tells the JVM to make sure that the changes are visible in the "correct order" which basically eliminates ambiguity around whether your main thread sees the changes made by other threads.

If your threads were doing things like adding and removing elements, or swapping them, you'd need to control changes to the structure with more elaborate synchronization constructs.

(Also, I don't think the array has to be static; you could just have it as an instance variable).
Was This Post Helpful? 2
  • +
  • -

#8 overwhelmed_student   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 63
  • Joined: 10-May 18

Re: Concurrency Multithreading

Posted 26 April 2019 - 07:25 AM

View Postxclite, on 26 April 2019 - 07:16 AM, said:

Do you think your work is CPU-bound, or IO-bound?


I have never heard those words before but I googled and I believe it is CPU-bound but I am not exactly sure yet. All I want to do is increment the numbers of my array. I increased the size to 1 million values which I think is a number big enough to see a difference. I think I just didn't do it right.
Was This Post Helpful? 0
  • +
  • -

#9 overwhelmed_student   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 63
  • Joined: 10-May 18

Re: Concurrency Multithreading

Posted 26 April 2019 - 07:34 AM

View Postxclite, on 26 April 2019 - 07:24 AM, said:

volatile tells the JVM to make sure that the changes are visible in the "correct order" which basically eliminates ambiguity around whether your main thread sees the changes made by other threads.

(Also, I don't think the array has to be static; you could just have it as an instance variable).


This is great, I didn't know something like volatile existed. However, even when I specifically gave my threads different names, I realized, that none of them appear to be running the run-method. It only prints out "main". I think, I don't even have more than the main-thread working on my array and I don't know why this didn't work. Any ideas? I created a new thread and I called the run-method. Why doesn't it do the work?

This post has been edited by overwhelmed_student: 26 April 2019 - 07:36 AM

Was This Post Helpful? 0
  • +
  • -

#10 xclite   User is offline

  • I wrote you an code
  • member icon


Reputation: 1380
  • View blog
  • Posts: 4,206
  • Joined: 12-May 09

Re: Concurrency Multithreading

Posted 26 April 2019 - 08:10 AM

View Postoverwhelmed_student, on 26 April 2019 - 10:25 AM, said:

I have never heard those words before but I googled and I believe it is CPU-bound but I am not exactly sure yet. All I want to do is increment the numbers of my array. I increased the size to 1 million values which I think is a number big enough to see a difference. I think I just didn't do it right.


I have a meeting in a second but will come back to your second question (about doing this right): for the first, you're manipulating a value in memory (this is another oversimplification), so your limiting factor is really just how fast you can manipulate that value. This is bound by the speed of your CPU and how quickly it can modify RAM, so I'd call this CPU-bound.
Was This Post Helpful? 1
  • +
  • -

#11 xclite   User is offline

  • I wrote you an code
  • member icon


Reputation: 1380
  • View blog
  • Posts: 4,206
  • Joined: 12-May 09

Re: Concurrency Multithreading

Posted 26 April 2019 - 08:22 AM

View Postoverwhelmed_student, on 26 April 2019 - 10:34 AM, said:

I created a new thread and I called the run-method. Why doesn't it do the work?

Compare what Thread.run does with what Thread.start does, and I think you'll find your answer.
Was This Post Helpful? 1
  • +
  • -

#12 overwhelmed_student   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 63
  • Joined: 10-May 18

Re: Concurrency Multithreading

Posted 26 April 2019 - 08:28 AM

View Postxclite, on 26 April 2019 - 08:22 AM, said:

Compare what Thread.run does with what Thread.start does, and I think you'll find your answer.


But the main thread is also executing the run-method. Does it always do that and I just didn't check it before?
Was This Post Helpful? 0
  • +
  • -

#13 xclite   User is offline

  • I wrote you an code
  • member icon


Reputation: 1380
  • View blog
  • Posts: 4,206
  • Joined: 12-May 09

Re: Concurrency Multithreading

Posted 26 April 2019 - 08:31 AM

I think you've lost me; can you post your updated code?
Was This Post Helpful? 1
  • +
  • -

#14 overwhelmed_student   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 63
  • Joined: 10-May 18

Re: Concurrency Multithreading

Posted 26 April 2019 - 08:39 AM

View Postxclite, on 26 April 2019 - 08:31 AM, said:

I think you've lost me; can you post your updated code?


Here it is:
public class ThreadPlay implements Runnable{
    private static int[] array = new int[1000000];
    public static int threadNo = 2;
    public static int start = 0;
    public static int end = array.length/threadNo;

    public void incrementValues(int[] array, int start, int end) {
        if(end > array.length || start >= end) {
            System.out.println("Error!");
        }
        else {
            for (int i = start; i < end; i++) {
                array[i] = array[i] + 1;
            }
        }
    }

    public void run() {
        System.out.println("Thread " + Thread.currentThread().getName() + " running.");
        incrementValues(array, start, end);
    }


    public static void main(String[] args) {
        System.out.println("Running on " + threadNo + " threads.");
        double time = System.currentTimeMillis();

        //create the threads
        for(int i = 1; i <= threadNo; i++) {
            Thread t = new Thread(new ThreadPlay());
            //to be able to see which thread is running
            t.setName("t" + i);
            t.start();
            t.run();
            start = end;
            end = end+(array.length/threadNo);
        }

        double stop = System.currentTimeMillis();
        //to see how long the execution takes
        System.out.println("Time: " + (stop - time) + "ms");  
    }
}


Was This Post Helpful? 0
  • +
  • -

#15 xclite   User is offline

  • I wrote you an code
  • member icon


Reputation: 1380
  • View blog
  • Posts: 4,206
  • Joined: 12-May 09

Re: Concurrency Multithreading

Posted 26 April 2019 - 08:44 AM

Ok, there's a lot to cover here.

  • Call ONLY start, not run.
  • Even better would be to submit these Runnables to an ExecutorService
  • Once you get the threads running concurrently, you're going to need a way to wait on them.
  • I really recommend obliterating your use of static. These values are shared across all threads, so when you modify "start" from the main thread, you modify it for all the threads. Instead, give the threads their positions in the constructor (when you call new).
  • I'd also recommend separating your main method from the things it is creating and running, which will help manage state.


I really really want to emphasize: If you want to write Good Code in Java, you should very rarely be using "static".
Was This Post Helpful? 1
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2