About Question enthuware.ocpjp.v8.2.1258 :

Help and support on OCA OCP Java Programmer Certification Questions
1Z0-808, 1Z0-809, 1Z0-815, 1Z0-816, 1Z0-817

Moderator: admin

Post Reply
schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

About Question enthuware.ocpjp.v8.2.1258 :

Post by schchen2000 »

Code: Select all

            int mid = (from+to)/2;
            ComplicatedTask newtask1 = new ComplicatedTask(ia, from, mid);
            ComplicatedTask newtask2 = new ComplicatedTask(ia, mid+1, to);
            newtask1.fork();

            int x = newtask2.compute();  //LINE A
            int y = newtask1.join(); //LINE B

            return x+y;
The order of join() and compute() is critical. Remember that fork() causes the sub-task to be submitted to the pool and another thread can execute that task in parallel to the current thread. Therefore, if you call join() on the newly created sub task, you are basically waiting until that task finishes. This means you are using up both the threads (current thread and another thread from the pool that executes the subtask) for that sub task. Instead of waiting, you should use the current thread to compute another subtask and when done, wait for another thread to finish. This means, both the threads will execute their respective tasks in parallel instead of in sequence.
Let's make sure we are all in agreement.

Based on what's in the quote,

the newly created subtask is "tied" another thread (say T1) from the pool.

The current thread (say T2) is "tied" to newtask2.compute() if I understand you correctly.

That's exactly what you meant in the quote, isn't it?

Once we agree on that, we need to wait for the subtask to finish after calling join() on that another thread from the pool.

Is that correct?

While waiting for the subtask to finish, why can't T2 just do newtask2.compute() and return the result to the int variable x and leave if it indeed finishes the work earlier than T1 can?

I got a sense (from your explanation in different colours in the above quote) that T2 must also "accompany" T1 while waiting for the subtask to finish. Why can't T2 leave early if it finishes what it needs to do?
Instead of waiting, you should use the current thread to compute another subtask and when done, wait for another thread to finish. This means, both the threads will execute their respective tasks in parallel instead of in sequence. Therefore, even though the final answer will be the same, the performance will not be the same.
This quote seem to be suggesting that T2 must "accompany" T1 and wait. It also seems to suggest that leaving if T2 finishes its work early and doing something else useful would have been a better way for T2 to be spending its time instead of wasting it by "hanging out with" T1.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by admin »


Based on what's in the quote,

the newly created subtask is "tied" another thread (say T1) from the pool.

The current thread (say T2) is "tied" to newtask2.compute() if I understand you correctly.

That's exactly what you meant in the quote, isn't it?
Not really. That is not "exactly" what is meant in the quote. The quote is trying to explain why the order of Line A and B is important. What it means is this - The call to join makes the caller thread wait until the callee thread finishes execution. The caller thread does nothing during that time. Therefore, if the current thread calls newtask1.join() before calling newtask2.compute(), the caller thread will first sit doing nothing until newtask1 is computed. After that, the current thread will proceed to newtask2.compute(). This effectively computes the two tasks in sequence instead of concurrently, which defeats the purpose of fork/join.
While waiting for the subtask to finish, why can't T2 just do newtask2.compute() and return the result to the int variable x and leave if it indeed finishes the work earlier than T1 can?
Not sure what you mean by "leave if indeed finishes the work earlier than T1 can". You need the value of x as well as of y because you want to calculate x+y.
I got a sense (from your explanation in different colours in the above quote) that T2 must also "accompany" T1 while waiting for the subtask to finish. Why can't T2 leave early if it finishes what it needs to do?
Again, not sure what you mean by "accompany" and "leave".


-Paul.
If you like our products and services, please help us by posting your review here.

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by schchen2000 »

Not really. That is not "exactly" what is meant in the quote. The quote is trying to explain why the order of Line A and B is important. What it means is this - The call to join makes the caller thread wait until the callee thread finishes execution. The caller thread does nothing during that time. Therefore, if the current thread calls newtask1.join() before calling newtask2.compute(), the caller thread will first sit doing nothing until newtask1 is computed. After that, the current thread will proceed to newtask2.compute(). This effectively computes the two tasks in sequence instead of concurrently, which defeats the purpose of fork/join.
Hi Paul,

Thanks. I just want to pick up on your answer that's in the quote above.

Caller thread = the thread that runs the compute() method (recursively) in the example. Is that correct?

Callee thread = the thread from the pool that runs the subtask submitted via newtask1.fork(). Is that correct?

In other words, the order of LINE A and LINE B

Code: Select all

int x = newtask2.compute();  //LINE A

int y = newtask1.join(); //LINE B
given in the problem is "the best" one could ask for because we do all the useful work by calling newtask2.compute() first and when we have nothing else better to do, we wait for newtask1 to finish by doing nothing but waiting before we return the final result in the compute() method.

The order of LINE B before LINE A would have been inefficient.

Do I understand your explanation in the quote correctly? Thanks again, Paul.

Schmichael

PS

BTW, what are the differences between the join() methods from the Thread Class and the ForkJoinTask Class?

My understanding is

the join() method from the Thread Class is used to wait for a thread to die. The thread is started when the run() method is internally called by the triggering of the start() method from the Thread Class.

The join() method from the ForkJoinTask is used to return the computation results when the task is done.

So, the conclusion (or perhaps "similarity") I can draw from the join() method of both Thread Class and ForkJoinTask Class would be as follows:

A thread dies under normal circumstances when all the useful work is done and after the result is returned. By normal, I mean threads running without any extraordinary circumstances such as exceptions and so on.

Is that a reasonable thing to say? Thanks again, Paul.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by admin »

schchen2000 wrote: Caller thread = the thread that runs the compute() method (recursively) in the example. Is that correct?
Yes.
Callee thread = the thread from the pool that runs the subtask submitted via newtask1.fork(). Is that correct?
Yes.
In other words, the order of LINE A and LINE B

Code: Select all

int x = newtask2.compute();  //LINE A

int y = newtask1.join(); //LINE B
given in the problem is "the best" one could ask for because we do all the useful work by calling newtask2.compute() first and when we have nothing else better to do, we wait for newtask1 to finish by doing nothing but waiting before we return the final result in the compute() method.

The order of LINE B before LINE A would have been inefficient.

Do I understand your explanation in the quote correctly? Thanks again, Paul.
Yes.
BTW, what are the differences between the join() methods from the Thread Class and the ForkJoinTask Class?
join of Thread class: the join method returns when the thread on which join is called dies (or is interrurpted).
join of ForkJoinTask: the join method returns when the computation is done. The thread that is used internally by the fork/join pool will go back to the pool. That thread is not "dead" but is sent back in the pool to do more work (if available).

My understanding is

the join() method from the Thread Class is used to wait for a thread to die. The thread is started when the run() method is internally called by the triggering of the start() method from the Thread Class.

The join() method from the ForkJoinTask is used to return the computation results when the task is done.

So, the conclusion (or perhaps "similarity") I can draw from the join() method of both Thread Class and ForkJoinTask Class would be as follows:

A thread dies under normal circumstances when all the useful work is done and after the result is returned. By normal, I mean threads running without any extraordinary circumstances such as exceptions and so on.

Is that a reasonable thing to say? Thanks again, Paul.
Yes.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by schchen2000 »

join of Thread class: the join method returns when the thread on which join is called dies (or is interrurpted).
Thanks, Paul. When you said "the join method returns," you meant returning "the control" back to a thread, perhaps something like the (main) thread represented by the main() method because the join method from the Thread Class returns void.

Does it mean that the main thread has to wait (even if it has nothing more left to do on its own) for the other thread to die when join() is called upon that other thread?

Can the main thread itself die before the other thread, upon which the join() method is called, can die?

Thanks, Paul.

Schmichael

PS

Theoretically speaking, the number of threads we can have is determined by the number of cores we have on CPU; however, the number of threads we can have in the fork/join setting is determined by the size of the ForkJoinPool. Is that correct, Paul? Thanks.
Last edited by schchen2000 on Thu Sep 22, 2016 5:39 pm, edited 1 time in total.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by admin »

schchen2000 wrote:
join of Thread class: the join method returns when the thread on which join is called dies (or is interrurpted).
Thanks, Paul. When you said "the join method returns," you meant returning "the control" back to a thread, perhaps something like the (main) thread represented by the main() method because the join method from the Thread Class returns void.
Yes.
Does it mean that the main thread has to wait (even if it has nothing more left to do on its own) for the other thread to die when join() is called upon that other thread?
Yes, the control will not go beyond the call to join until join returns. The thread that calls join will wait until join returns.
Can the main thread itself die before the other thread, upon which the join() method is called, can die?
No, the thread that has called join cannot die before the other thread because it is waiting for join to return!
If you like our products and services, please help us by posting your review here.

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by schchen2000 »

Thanks for your last answer. Just to double-check, I'm wondering if you were basing your previous answer on the join() method from Thread Class. As there are join() methods from both Thread Class and ForkJoinTask Class, I just want to make sure I seek the answers to my questions for the join() method from Thread Class. Thanks.

I just updated my earlier question with
PS

Theoretically speaking, the number of threads we can have is determined by the number of cores we have on CPU; however, the number of threads we can have in the fork/join setting is determined by the size of the ForkJoinPool. Is that correct, Paul? Thanks.
but my update came in a bit later after your answer. Would you mind having a look at my PS? I'm sorry about getting you to look at the same post twice. My apology. Thanks.

Schmichael

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by admin »

schchen2000 wrote:Thanks for your last answer. Just to double-check, I'm wondering if you were basing your previous answer on the join() method from Thread Class.
Yes.

PS

Theoretically speaking, the number of threads we can have is determined by the number of cores we have on CPU; however, the number of threads we can have in the fork/join setting is determined by the size of the ForkJoinPool. Is that correct, Paul? Thanks.
1. No, you can have any number of threads. It has nothing to do with number of CPU cores.
2. Number of threads used by ForkJoinPool is, by default, same as the number of CPU cores. You can create a pool with less threads. Please go through the API: https://docs.oracle.com/javase/7/docs/a ... rkJoinPool()
If you like our products and services, please help us by posting your review here.

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by schchen2000 »

admin wrote:
schchen2000 wrote:Thanks for your last answer. Just to double-check, I'm wondering if you were basing your previous answer on the join() method from Thread Class.
Yes.

PS

Theoretically speaking, the number of threads we can have is determined by the number of cores we have on CPU; however, the number of threads we can have in the fork/join setting is determined by the size of the ForkJoinPool. Is that correct, Paul? Thanks.
1. No, you can have any number of threads. It has nothing to do with number of CPU cores.
2. Number of threads used by ForkJoinPool is, by default, same as the number of CPU cores. You can create a pool with less threads. Please go through the API: https://docs.oracle.com/javase/7/docs/a ... rkJoinPool()
Thank you very much.

Schmichael

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by schchen2000 »

My earlier question

Theoretically speaking, the number of threads we can have is determined by the number of cores we have on CPU; however, the number of threads we can have in the fork/join setting is determined by the size of the ForkJoinPool. Is that correct, Paul? Thanks.

Your earlier answer

1. No, you can have any number of threads. It has nothing to do with number of CPU cores.
2. Number of threads used by ForkJoinPool is, by default, same as the number of CPU cores. You can create a pool with less threads. Please go through the API: https://docs.oracle.com/javase/7/docs/a ... rkJoinPool()

My new question
Number of threads used by ForkJoinPool is, by default, same as the number of CPU cores. You can create a pool with less threads.
When we can create a pool with less threads, why can't we have more threads than the number of CPU cores? Wouldn't context switching take care of it when we have more threads in the pool than the number of CPU cores?

My new question on Executors Class (Different class from all my previous questions)

What about the thread pool from Executors Class? For instance, the method like newFixedThreadPool(int desired_thread_number). Is the number of threads in such a thread pool from Executors Class limited by anything such as number of available CPU's? Can that thread number in the pool be any number? I read the Oracle documentation on Executors Class and unable to find that information. Thanks.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by admin »

schchen2000 wrote: When we can create a pool with less threads, why can't we have more threads than the number of CPU cores? Wouldn't context switching take care of it when we have more threads in the pool than the number of CPU cores?
The API documentation doesn't provide any reason but here is my take:
The whole point of submitting tasks to fork join pool is to be able to actually execute them concurrently. If you create more threads than the number of cores, there is no advantage. In fact, it will be less efficient because of context switching.
schchen2000 wrote: My new question on Executors Class (Different class from all my previous questions)

What about the thread pool from Executors Class? For instance, the method like newFixedThreadPool(int desired_thread_number). Is the number of threads in such a thread pool from Executors Class limited by anything such as number of available CPU's? Can that thread number in the pool be any number? I read the Oracle documentation on Executors Class and unable to find that information. Thanks.
If the documentation doesn't specify any limitation then there is no limitation. You can try creating a sample program with varying number of threads and see if runs without any exception.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

schchen2000
Posts: 106
Joined: Mon Mar 28, 2016 11:36 pm
Contact:

Re: About Question enthuware.ocpjp.v8.2.1258 :

Post by schchen2000 »

If the documentation doesn't specify any limitation then there is no limitation. You can try creating a sample program with varying number of threads and see if runs without any exception.
Paul, thanks for your answer. It's confirmed that there is no limit on the number of threads that can be in the thread pool of the Executors Class. It's confirmed by the Oracle documentation on the following method:
public static ExecutorService newCachedThreadPool()

Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. Calls to execute will reuse previously constructed threads if available. If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources. Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors.

Returns:
the newly created thread pool
Reference: https://docs.oracle.com/javase/7/docs/a ... ThreadPool()

Post Reply

Who is online

Users browsing this forum: No registered users and 33 guests