Swing Worker Threads Not Concurrent - java

It seems that when I instantiate 12 Swing Worker threads, the first six starts to complete its task, it finishes AND then the last six starts and finishes. The behavior I'm looking for is all 12 threads start working at the same time & finish at the same time.
I have the following:
for (int i = 0; i < 12; i++ )
{
myTask m = new Mytask(i, START);
m.execute();
}
The myTask m will increment a progress bar from 0 - 100 in increments of 25. I'm getting outlandish behavior that the first six threads start incrementing, they finish at 100, then the last six threads start from 0 and increment, and finish.
Is there a limiting factor on the amount of Swing Worker threads one may have?

The behavior I'm looking for is all 12 threads start working at the same time & finish at the same time.
A CountDownLatch is designed for this very purpose. Here's a good example using a single SwingWorker and a number of subsidiary threads controlled by the latch.

SwingWorker class has a static ExecutorService field with MAX_WORKER_THREADS = 10. I'm not certain why you see 6 and not 10. But you cannot go over 10.
/**
* number of worker threads.
*/
private static final int MAX_WORKER_THREADS = 10;
...
executorService =
new ThreadPoolExecutor(1, MAX_WORKER_THREADS,
10L, TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>(),
threadFactory);

Your question says:
The behavior I'm looking for is all 12
threads start working at the same time
& finish at the same time.
But you can't guarantee for all Swing workers threads starting concurrently and ending at same time.

Related

Amount of Threads with subtasks

An optimum of threads in a pool is something that is case specific, though there is a rule of thumb which says #threads = #CPU +1.
However, how does this work with threads spanning other threads and waiting (i.e. blocked until thread.join() is successful) for these 'subthreads'?
Assume that I have code that requires the execution of list of tasks (2), which has subtasks(2), which has subsubtasks(3) and so on. The total number of tasks is 2*2*3 = 12, though 18 threads will be created (because a threads will 'spawn' more subtasks (threads), where the thread spawning more threads will be blocked untill all is over. See below for pseudo code.
I am assuming that for a CPU with N cores there is a rule of thumb that everything can be parallelized if the highest number of active threads (12) is #CPU + 1. Is this correct?
PseudoCode
outputOfTask = []
for subtask in SubTaskList
outputOfTask --> append(subtask.doCompute())
// wait untill all output is finished.
in subtask.java:
Each subtask, for example, implements the same interface, but can be different.
outputOfSubtask = []
for task in subsubTaskList
// do some magic depending on the type of subtask
outputOfSubtask -> append( task.doCompute())
return outputOfSubtask
in subsubtask.java:
outputOfSubsubtask = []
for task in subsubsubtask
// do some magic depending on the type of subsubtask
outputOfSubsubtask -> append( task.doCompute())
return outputOfSubsubtask
EDIT:
Dummy code Java code. I used this in my original question to check how many threads were active, but I assume that the pseudocode is more clear. Please note: I used the Eclipse Collection, this introduces the asParallel function which allows for a shorter notation of the code.
#Test
public void testasParallelthreads() {
// // ExecutorService executor = Executors.newWorkStealingPool();
ExecutorService executor = Executors.newCachedThreadPool();
MutableList<Double> myMainTask = Lists.mutable.with(1.0, 2.0);
MutableList<Double> mySubTask = Lists.mutable.with(1.0, 2.0);
MutableList<Double> mySubSubTask = Lists.mutable.with(1.0, 2.0);
MutableList<Double> mySubSubSubTask = Lists.mutable.with(1.0, 2.0, 2.0);
MutableList<Double> a = myMainTask.asParallel(executor, 1)
.flatCollect(task -> mySubTask.asParallel(executor,1)
.flatCollect(subTask -> mySubSubTask.asParallel(executor, 1)
.flatCollect(subsubTask -> mySubSubSubTask.asParallel(executor, 1)
.flatCollect(subsubTask -> dummyFunction(task, subTask, subsubTask, subsubTask,executor))
.toList()).toList()).toList()).toList();
System.out.println("pool size: " + ((ThreadPoolExecutor) executor).getPoolSize());
executor.shutdownNow();
}
private MutableList<Double> dummyFunction(double a, double b, double c, double d, ExecutorService ex) {
System.out.println("ThreadId: " + Thread.currentThread().getId());
System.out.println("Active threads size: " + ((ThreadPoolExecutor) ex).getActiveCount());
return Lists.mutable.with(a,b,c,d);
}
I am assuming that for a CPU with N cores there is a rule of thumb that everything can be parallelized if the highest number of active threads (12) is #CPU + 1. Is this correct?
This topic is extremely hard to generalize about. Even with the actual code, the performance of your application is going to be very difficult to determine. Even if you could come up an estimation, the actual performance may vary wildly between runs – especially considering that the threads are interacting with each other. The only time we can take the #CPU + 1 number is if the jobs that are submitted into the thread-pool are independent and completely CPU bound.
I'd recommend trying a number of different thread-pool size values under simulated load to find the optimal values for your application. Examining the overall throughput numbers or system load stats should give you the feedback you need.
However, how does this work with threads spanning other threads and waiting (i.e. blocked until thread.join() is successful) for these 'subthreads'?
Threads will block, and it is up to the os/jvm to schedule another one if possible. If you have a single thread pool executor and call join from one of your tasks, the other task won't even get started. With executors that use more threads, then the blocking task will block a single thread and the os/jvm is free to scheduled other threads.
These blocked threads should not consume CPU time, because they are blocked. So I am assuming that for a CPU with N cores there is a rule of thumb that everything can be parallelized if the highest number of active threads (24) is #CPU + 1. Is this correct?
Active threads can be blocking. I think you're mixing terms here, #CPU, the number of cores, and the number of virtual cores. If you have N physical cores, then you can run N cpu bound tasks in parallel. When you have other types of blocking or very short lived tasks, then you can have more parallel tasks.

Join a group of threads with overall timeout

Is there a way to join a group of threads simultaneously with an overall timeout?
Suppose we have Collection<Thread> threads; and int timeout;. If I didn't care about the timeout, I would do
for (Thread t : threads)
t.join();
but I want to wait until either all threads are done, or a certain amount of time passes, whichever comes first. I was searching for a (hypothetical) ThreadGroup.join(int) which would do this.
Note that what I'm asking for is different from doing
for (Thread t : threads)
t.join(timeout);
Rather, I'm looking for something less verbose (and perhaps more reliable) than
int timeout = 10000;
for (Thread t : threads) {
if (timeout <= 0) break;
long start = System.currentTimeMillis();
t.join(timeout);
long end = System.currentTimeMillis();
// substract time elapsed from next timeout:
timeout -= (int) (end - start);
}
First create a single CountDownLatch having a count for every thread in the group.
A controlling thread can await(timeout, TimeUnit) on the latch.
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html#await-long-java.util.concurrent.TimeUnit-
Start the threads that are in the group.
Each of the threads in the group should decrement the latch when it completes.
The controlling thread will wait until everything in the group has completed or the timeout happens, and because await returns a boolean, the controlling thread can tell whether the latch was decremented naturally or whether a timeout occurred.

Threads run in serial not parallel

I am trying to learn concurrency in Java, but whatever I do, 2 threads run in serial, not parallel, so I am not able to replicate common concurrency issues explained in tutorials (like thread interference and memory consistency errors). Sample code:
public class Synchronization {
static int v;
public static void main(String[] args) {
Runnable r0 = () -> {
for (int i = 0; i < 10; i++) {
Synchronization.v++;
System.out.println(v);
}
};
Runnable r1 = () -> {
for (int i = 0; i < 10; i++) {
Synchronization.v--;
System.out.println(v);
}
};
Thread t0 = new Thread(r0);
Thread t1 = new Thread(r1);
t0.start();
t1.start();
}
}
This always give me a result starting from 1 and ending with 0 (whatever the loop length is). For example, the code above gives me every time:
1
2
3
4
5
6
7
8
9
10
9
8
7
6
5
4
3
2
1
0
Sometimes, the second thread starts first and the results are the same but negative, so it is still running in serial.
Tried in both Intellij and Eclipse with identical results. CPU has 2 cores if it matters.
UPDATE: it finally became reproducible with huge loops (starting from 1_000_000), though still not every time and just with small amount of final discrepancy. Also seems like making operations in loops "heavier", like printing thread name makes it more reproducible as well. Manually adding sleep to thread also works, but it makes experiment less cleaner, so to say. The reason doesn't seems to be that first loop finishes before the second starts, because I see both loops printing to console while continuing operating and still giving me 0 at the end. The reasons seems more like a thread race for same variable. I will dig deeper into that, thanks.
Seems like first started thread just never give a chance to second in Thread Race to take a variable/second one just never have a time to even start (couldn't say for sure), so the second almost* always will be waiting until first loop will be finished.
Some heavy operation will mix the result:
TimeUnit.MILLISECONDS.sleep(100);
*it is not always true, but you are was lucky in your tests
Starting a thread is heavyweight operation, meaning that it will take some time to perform. Due that fact, by the time you start second thread, first is finished.
The reasoning why sometimes it is in "revert order" is due how thread scheduler works. By the specs there are not guarantees about thread execution order - having that in mind, we know that it is possible for second thread to run first (and finish)
Increase iteration count to something meaningful like 10000 and see what will happen then.
This is called lucky timing as per Brian Goetz (Author of Java Concurrency In Practice). Since there is no synchronization to the static variable v it is clear that this class is not thread-safe.

FixedThreadPool

What I need to do is use a FixedThreadPool of size 3 and then use it to print the ThreadName and then make it go to sleep for a random amount of time within a specified time interval and print that it is awake when it is done. I need to do it thread by thread but my output is coming with all the 3 threads together.
Desired output:
pool-1-thread-1 Going to sleep for random amount of time interval between 800 ms and 1000ms
pool-1-thread-1 done sleeping
pool-1-thread-2 Going to sleep for random amount of time interval between 800 ms and 1000ms
pool-1-thread-2 done sleeping
pool-1-thread-3 Going to sleep for random amount of time interval between 800 ms and 1000ms
pool-1-thread-3 done sleeping
I need to use FixedThreadPool only
import java.util.Random;
import java.util.concurrent.*;
class Sleep implements Runnable
{
public void run()
{
Random ran = new Random();
int randomnumber = ran.nextInt(1000-800+1)+800;
System.out.print(Thread.currentThread().getName()+" ");
System.out.println("Going to sleep for random amount of time interval between 800 ms and 1000ms");
try
{
Thread.sleep(randomnumber);
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" done sleeping");
Thread.yield();
}
}
public class Ch6Ex3
{
public static void main(String[] args)
{
ExecutorService exe = Executors.newFixedThreadPool(3);
for(int i=0;i<3;i++)
{
exe.execute(new Sleep());
}
exe.shutdown();
}
}
Create thread pool with only 1 thread. If you use 3 threads then up to 3 runnable can be run concurrently and it's not what you want. So use:
ExecutorService exe = Executors.newFixedThreadPool(1);
Actually better option will be to use newSingleThreadExecutor because it explicitly shows that it runs only 1 runnable at any given time:
ExecutorService exe = Executors.newSingleThreadExecutor();
Internally both methods create ThreadPoolExecutor with 1 thread so there is no actual difference between them only in naming.
If you're creating the objects immediately after one another (within the same ms), they'll probably have the same seed in their Random instances - therefore they'll sleep for the same amount of time.
From javadoc:
Creates a new random number generator. Its seed is initialized to a value based on the current time:
public Random() { this(System.currentTimeMillis()); }
Two Random objects created within the same millisecond will have the same sequence of random numbers.
Besides that there's a problem in your code.
Thread.yield();
is redundant.
If you need that to execute one by one you don't need thread pool. You may just invoke Sleep#run from within your for loop creating different instances of Sleep class.
If you need that to work using FixedThreadPool and you wanna exactly 3 separate threads done your work you should use Locks. Like this: First thread is locking your Lock on entrance and unlocking on exit. Next threads will wait for Lock to relase and do the same stuff.
Read more here:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html

Why is my threaded sort algorithm slow compared to the non-threaded version?

I just have implemented a threaded version of the merge sort. ThreadedMerge.java: http://pastebin.com/5ZEvU6BV
Since merge sort is a divide and conquer algorithm I create a thread for every half of the array. But the number of avialable threads in Java-VM is limited so I check that before creating threads:
if(num <= nrOfProcessors){
num += 2;
//create more threads
}else{
//continue without threading
}
However the threaded sorting takes about ~ 6000 ms while the non-threaded version is much faster with just ~ 2500 ms.
Non-Threaded: http://pastebin.com/7FdhZ4Fw
Why is the threaded version slower and how do I solve that problem?
Update: I use atomic integer now for thread counting and declared a static field for Runtime.getRuntime().availableProcessors(). The sorting takes about ~ 1400 ms now.
However creating just one thread in the mergeSort method and let the current thread do the rest has no sigificant performance increase. Why?
Besides when after I call join on a thread and after that decrement the number of used threads with
num.set(num.intValue() - 1);
the sorting takes about ~ 200 ms longer. Here is the update of my algorithm http://pastebin.com/NTZq5zQp Why does this line of code make it even worse?
first off your accesses to num is not threadsafe (check http://download.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicInteger.html )
you create an equal amount of processes to cores but you block half of them with the join call
num += 1;
ThreadedMerge tm1 = new ThreadedMerge(array, startIndex, startIndex + halfLength);
tm1.start();
sortedRightPart = mergeSort(array, startIndex + halfLength, endIndex);
try{
tm1.join();
num-=1
sortedLeftPart = tm1.list;
}catch(InterruptedException e){
}
this doesn't block the calling thread but uses it to sort the right part and let the created thread do the other part when that one returns the space it takes up can be used by another thread
Hhm, you should not create a thread for every single step (they are expensive and there are lightweight alternatives.)
Ideally, you should only create 4 threads if there are 4 CPU´s.
So let´s say you have 4 CPU´s, then you create one thread at the first level (now you have 2) and at the second level you also create a new thread. This gives you 4.
The reason why you only create one and not two is that you can use the thread you are currently running like:
Thread t = new Thread(...);
t.start();
// Do half of the job here
t.join(); // Wait for the other half to complete.
If you have, let´s say, 5 CPU´s (not in the power of two) then just create 8 threads.
One simple way to do this in practice, is to create the un-threaded version you already made when you reach the appropriate level. In this way you avoid to clutter the merge method when if-sentences etc.
The call to Runtime.availableProcessors() appears to be taking up a fair amount of extra time. You only need to call it once, so just move it outside of the method and define it as a static, e.g.:
static int nrOfProcessors = Runtime.getRuntime().availableProcessors();

Categories

Resources