Java - multiple Runnables per Thread - java

I got a fixed number of threads. I want each thread to run three Runnables, one after another. Here's some pseudocode to explain:
Thread[] threads = new Thread[4];
for (int i = 0; i < threads.length; i++) {
// Set the first tasks.
threads[i] = new Thread(new FirstRunnable());
threads[i].start();
}
for (int i = 0; i < threads.length; i++)
threads[i].join(); // wait until the first tasks are done
for (int i = 0; i < threads.length; i++) {
// Set the second task.
threads[i].setRunnable(new SecondRunnable());
threads[i].start();
}
for (int i = 0; i < threads.length; i++)
threads[i].join(); // wait until the second tasks are done
...
Using a ThreadPool sounds way overkill, especially since I'm headed for performance, performance, performance. What's the best way to implement this in Java?

Whenever you see new Thread(...).start(), make use of the Executors framework. In particular, make use of Executors.newFixedThreadPool(...).

Seems like a good use for a newFixedThreadPool from the Executors class.
So your code would look something like:
ExecutorService es = Executors.newFixedThreadPool(4);
List<Future> futures = new ArrayList<Future>();
for (int x = 0; x < 4; x ++) {
futures.add(es.submit(new FirstRunnable()));
}
while (futures.size() > 0) {
futures.remove(0).get();
}
for (int x = 0; x < 4; x ++) {
futures.add(es.submit(new SecondRunnable()));
}
while (futures.size() > 0) {
futures.remove(0).get();
}
Of course, you could probably easily refactor the code above to remove code duplication.

You can use a CyclicBarrier and a "CombinedRunnable" as shown below. The barrier allows the threads to all wait for each other to finish, before proceeding to the next runnable.
CyclicBarrier barrier = new CyclicBarrier(4);
Runnable r = new CombinedRunnable(barrier, new FirstRunnable(), new SecondRunnable());
Thread[] threads = new Thread[4];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(r);
threads[i].start();
}
The CombinedRunnable class:
public class CombinedRunnable implements Runnable{
private final CyclicBarrier barrier;
private final Runnable[] runnables;
public CombinedRunnable(CyclicBarrier barrier, Runnable... runnables){
this.barrier = barrier;
this.runnables = runnables;
}
/* (non-Javadoc)
* #see java.lang.Runnable#run()
*/
#Override
public void run() {
for(Runnable r: runnables){
r.run();
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}

An idiomatic way to achieve this is by using an Executor in conjunction with a CompletionService. This allows you to map many units of work to a fixed size pool of threads and also provides an elegant mechanism for blocking until all work is complete.
Note that your concern about how using a thread pool might impact efficiency is not really an issue: The main overhead is in creating individual threads, which you were doing anyway; the additional object creation overhead in creating a pool will be negligible.
// Create fixed thread pool and wrap in a CompletionService to allow for easy access to completed tasks.
// We don't have an explicit result for each Runnable so parameterise the service on Void.
CompletionService<Void> cs = new ExecutorCompletionService<Void>(Executors.newFixedThreadPool(3));
// Create units of work for submission to completion service.
Runnable[] runnables = ...
// Submit runnables. Note that we don't care about the result so pass in null.
for (Runnable r : runnables) {
cs.submit(r, null);
}
// Take each *completed* result in turn, blocking until a completed result becomes available.
for (int i=0; i<runnables.length; ++i) {
Future<Void> completed = cs.take();
}

Executor Framework is just for you.
Here's the pseudocode:
1. Create executor service
Executors type1Runnables = Executors.newFixedThreadPool(4);
Executors type2Runnables = Executors.newFixedThreadPool(4);
etc..
2. Submit tasks to it
for(){
type1Runnables.submit(new Runnable1());
type2Runnables.submit(new Runnable2);
}
3. Invoke the executors
type1Runnables.invokeAll();
type2Runnables.invokeAll();
To make it more generic you could perhaps write your own executorservicefactory which accepts the different runnable types.

Related

ExecutorService to execute a single task n times by multiple threads (n thread "races")

I need to execute a single task by multiple threads, such that when the first thread finishes and before any other thread finishes, all the threads are stopped and start the same task all over again. This should be performed n times.
My attempt is using Callable<V> and the method invokeAny() (that is why I use the set) but not sure how to accomplish the goal.
ExecutorService executor = Executors.newFixedThreadPool(10);
Callable<String> task = () -> {
someTask();
return "";
};
Set<Callable<String>> tasks = new HashSet<>();
IntStream.range(0, n).forEach(i -> {
tasks.add(task);
executor.submit(task);
});
How to finish this? or any better solution?
Here's one suggestion:
class Task implements Callable<Integer> {
private final static Random RND = new Random();
#Override
public Integer call() throws Exception {
try {
// Work on task for a random duration
Thread.sleep(RND.nextInt(5000));
} catch (InterruptedException e) {
System.err.println("I was interrupted."
+ "Someone else probably solved the task before me.");
return -1;
}
// Return some dummy value
return RND.nextInt();
}
}
class Scratch {
public static void main(String[] args) throws InterruptedException {
final int numWorkers = 3; // number of tasks to run in parallel
ExecutorService executor = Executors.newFixedThreadPool(numWorkers);
// Solve task 5 times. (Change it to while (true) { ...} if you like.)
for (int i = 0; i < 5; i++) {
CompletionService<Integer> completionService =
new ExecutorCompletionService<>(executor);
Future<?>[] futures = new Future<?>[numWorkers];
for (int j = 0; j < numWorkers; j++) {
futures[j] = completionService.submit(new Task());
}
Future<Integer> firstToComplete = completionService.take();
try {
Integer result = firstToComplete.get();
System.err.println("We got a result: " + result);
} catch (ExecutionException e) {
// Should not happen. Future has completed.
}
// Cancel all futures (it doesn't matter that we're cancelling
// the one that has already completed).
for (int j = 0; j < numWorkers; j++) {
futures[j].cancel(true);
}
}
executor.shutdown();
}
}
If the task you're solving does not respond to interrupts, passing true to cancel(...) won't help. In that case I'd suggest you do the following changes:
Create an AtomicBoolean done variable in the outer for loop.
Pass this to the constructor to Task and save it in a field in Task.
In the task solving process, check done flag ever so often, and cancel the attempt if done is true.
Instead of calling cancel on the tasks after the first result is in, set done to true and wait for the other threads to return.

Synchronized keyword Java speed effienciency

Feel free to correct me if I am wrong!
The synchronized keyword in java makes a method unable to be run be different threads simultaneously. In my program I have 4 different threads that run on the same time counting to 100.000.
When adding the synchronized keyword to the method being performed, it should take four times the amount of time as it would multithreading?
Executing the programs either way, takes roughly 16 seconds.
Heres my code!
public class ExerciseThree {
public static void main(String[] args) {
Even even = new Even();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
System.out.println(even.next());
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
System.out.println(even.next());
}
});
Thread t3 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
System.out.println(even.next());
}
});
Thread t4 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
System.out.println(even.next());
}
});
System.out.println("starting thread 1");
t1.start();
System.out.println("starting thread 2");
t2.start();
System.out.println("starting thread 3");
t3.start();
System.out.println("starting thread 4");
t4.start();
}
}
The method being called by the threads
public class Even {
private int n = 0;
// public synchronized int next() {
public int next() {
n++;
n++;
return n;
}
}
As already pointed out in the comment section, microbenchmarking is a complex matter as many factors influence the execution time (e.g., just-in-time compilation and garbage collection). A good reference was already provided in the comments section, but I suggest that you also take a look at my answer for a similar question which links to an external resource by Peter Sestoft that provides a very good introduction to microbenchmarking and what one needs to be aware of.
It has already been mentioned that println() has no place in a microbenchmark like this. In addition, I'd like to point out that you should use some sort of synchronization mechanism (e.g., a CountDownLatch) to make sure that the four threads start performing their work at the same time. The overhead involved in creating and starting the threads may result in the earlier threads getting a headstart on their work during the time it takes for the later ones to start, thereby creating less contention for the even lock than what you expect. This could for example look something like this:
public class ExerciseThree {
public static void main(String[] args) {
final CountDownLatch startSignal = new CountDownLatch(1);
final CountDownLatch threadReadyCheck = new CountDownLatch(4);
final CountDownLatch threadDoneCheck = new CountDownLatch(4);
Even even = new Even();
Thread t1 = new Thread(() -> {
threadReadyCheck.countDown();
startSignal.await();
for (int i = 0; i < 100000; i++) {
even.next();
}
threadDoneCheck.countDown();
});
Thread t2 = new Thread(() -> {
threadReadyCheck.countDown();
startSignal.await();
for (int i = 0; i < 100000; i++) {
even.next();
}
threadDoneCheck.countDown();
});
Thread t3 = new Thread(() -> {
threadReadyCheck.countDown();
startSignal.await();
for (int i = 0; i < 100000; i++) {
even.next();
}
threadDoneCheck.countDown();
});
Thread t4 = new Thread(() -> {
threadReadyCheck.countDown();
startSignal.await();
for (int i = 0; i < 100000; i++) {
even.next();
}
threadDoneCheck.countDown();
});
t1.start();
t2.start();
t3.start();
t4.start();
// Wait until all threads are ready to perform their work.
threadReadyCheck.await();
// All threads ready.
// This is where you log start time.
long start = System.nanoTime();
// Let threads progress to perform their actual work.
startSignal.countDown();
// Wait for threads to finish their work.
threadDoneCheck.await();
long end = System.nanoTime();
// Note that this is again subject to many factors, for example when the main thread gets scheduled again after the workers terminate.
long executionTime = end - start;
}
}
With println being much more expensive than the computation, it's all about concurrent execution of it. However, println itself is synchronized, so there can be no speed up.
Without it, doing just
public int next() {
n++;
n++;
return n;
}
is subject to many optimizations. Especially the double increment can be replaced by n+=2 and the return gets eliminated as the returned value doesn't get used. A loop like
for (int i = 0; i < 100000; i++) {
even.next());
}
can be reduced to just n += 200000.
Benchnmarking is hard in general and especially in Java. By all means, use JMH, which takes care of most problems.

Multithreading not working - Create thread per loop index Java

I wrote the below code trying to run two threads for calling a function in a for loop, but the results have the same time as if I ran it sequentially without multiple threads. Any thoughts why the multithreading here is not working? Is there a better way to do it? Like for example if I wanted to have 10 threads, using my code this will mean I have to create 10 duplicate run() functions when creating the thread, I wonder if there is an easier way to set the number of threads? Also is it possible to create a number of threads depending on the loop counter so that each loop a thread is created to finish it so if I had 10 loops then 10 threads will run concurrently to finish the processing very fast?
private Thread t1 = new Thread(){
public void run(){
for (int i = 0; i < 2; i++)
{
try {
myfn(i);
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
private Thread t2 = new Thread(){
public void run(){
for (int i = 2; i < 4; i++)
{
try {
myfn(i);
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
public Results getResults() throws IOException, SocketTimeoutException {
t1.start();
t2.start();
try {
t1.join(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
t2.join(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
For running the same task across multiple threads, you're probably looking for a thread pool. Java provides a ThreadPoolExecutor for this.
Here is an introduction to Java concurrency with the following example:
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> future = executor.submit(() -> {
try {
TimeUnit.SECONDS.sleep(2);
return 123;
}
catch (InterruptedException e) {
throw new IllegalStateException("task interrupted", e);
}
});
future.get(1, TimeUnit.SECONDS);
That example specifically creates a pool with only a single thread, but the parameter to Executors.newFixedThreadPool controls how many threads will be used.
I'm not sure from your original question why you think two threads aren't being utilized.
public class MyThead extend Thread{
private int initValue = 0;
private int upperBound = 0;
public MyThread(int init, int ub){
this.initValue = init;
this.upperBound = ub;
}
public void run(){
for(int i = init; i < upperBound; i++){
myfn(i);
}
}
}
Create threads and start them:
List<Thread> threads = new ArrayList<>();
threads.add(new MyThread(0,2));
threads.add(new MyThread(2,4));
for(Thread t: threads){
t.start()
}
for(Thread t: threads){
t.join();
}
I wrote the below code trying to run two threads for calling a function in a for loop, but the results have the same time as if I ran it sequentially without multiple threads.
There are many reasons why that can happen although it's hard to know what is going on without seeing the myfn(...) code. Here are some possible reasons:
It could be that myfn runs so quickly that running it in different threads isn't going to be any faster.
It could be that myfn is waiting on some other resource in which case the threads can't really run concurrently.
It could be that myfn is blocking on IO (network or disk) and even though you are doing 2 (or more) of them at a time, the disk or the remote server can't handle the increased requests any faster.
Is there a better way to do it? Like for example if I wanted to have 10 threads, using my code this will mean I have to create 10 duplicate run() functions...
The right thing to do here is to create your own class which takes the lower and upper bounds. The right way to do this is to implement Runnable, not extend Thread. Something like:
public class MyRunnable implements Runnable {
private final int start;
private final int end;
public MyRunnable(int start, int end) {
this.start = start;
this.end = end;
}
public void run() {
for (int i = start; i < end; i++) {
myfn(i);
}
}
}
You can then either start the threads by hand or use an ExecutorService which makes the thread maintenance a lot easier:
// this will start a new thread for every job
ExecutorService threadPool = Executors.newCachedThreadPool();
threadPool.submit(new MyRunnable(0, 2));
threadPool.submit(new MyRunnable(2, 4));
// once you've submitted your last task, you shutdown the pool
threadPool.shutdown();
// then we wait until all of the tasks have run
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
You don't need to copy your threads / loop 10 times, just take the logic and use it appropriately.
public class ExampleThread extends Thread {
private final int start, iterations;
public ExampleThread(int start, int iterations) {
this.start = start;
this.iterations = iterations;
}
#Override public void run() {
for (int i = 0; i < iterations; i++) {
myfn(start + i);
}
}
}
int iterations = 2;
List<Thread> threads = new ArrayList<>();
for (int threadId = 0; threadId < 10; threadId++) {
threads.add(new ExampleThread(threadId * iterations, iterations));
}
threads.forEach(Thread::start);
threads.forEach(t -> {
try {
t.join(0);
} catch (Exception e) {
e.printStackTrace(System.err);
}
});

Multiplle Threads in Java

I have a loop for example for (int i=1;i<=10;i++) and I want to create 10 threads inside it, each one to perform the same task on a set of data and return the result. Then process this result inside the loop. Any ideas how this can be done?
for (int i=1;i<=10;i++) {
Work w = new Work();
Thread t = new Thread(w);
w.getResultFromThread();
//process w
}
class Work implements Runnable {
public void run() {
//perform tasks
}
public int getResultFromThread() {
return result;
}
}
I want each thread to work in parallel but when I recieve the result to be one by one.
If you do not wish to use executors, the you can do it in the following way:
int size = 10;
Thread[] threads = new Thread[size];
Work[] works = new Work[size];
for (int i = 1; i <= size; i++) {
Work w = new Work();
works[i - 1] = w;
Thread t = new Thread(w);
threads[i - 1] = t;
// Start the thread
t.start();
}
// now you have started all the threads
for (int i = 0; i < size; i++) {
// wait for each thread to complete execution, before extracting the result
// [here i am assuming that getResultFromThread() does not block
// till we get the result, if it blocks, then no need to join]
threads[i].join();
int result = works[i].getResultFromThread();
// do something with the result
}
ArrayList<Work> listOfJobs = new ArrayList<Work>();
ArrayList<Thread> threadList = new ArrayList<Thread>();
for(int i = 0 ; i < 10; i++) {
Work w = new Work();
listOfJobs.add(w);
Thread t = new Thread(w);
threadList.add(t);
t.start();
}
for(Thread t : listOfJobs) {
t.join();
w.getResultsFromThread();
}
This way you don't need executors for whatever reason you might have not to use them.
First, you create all the threads and start them(1st loop), then you call join on them, to make sure thread you want to get results from is done(2nd loop).
You can always pass your listOfJobs to some other method to process your results.

Create ten instances of a class simultaneously using threads

I am trying to understand threads in Java. As an exercise, I created an Ice Cream class as follows.
public class ThreadIceCream {
private String flavor = "";
private String[] specialFlavors = { "Vanilla", "Chocolate", "Butter Pecan", "Strawberry", "Chocolate Chip", "Cherry", "Coffee" };
// Constructor for ThreadIceCream class
public ThreadIceCream() {
int randInt = (int) (Math.random() * specialFlavors.length);
flavor = specialFlavors[randInt];
System.out.println("Enjoy your " + flavor + " IceCream!");
} }
The ThreadIceCream class is a simple class that creates an IceCream object with a random flavor every time the class is initialized. Here is the TestStub I am using.
public class TestStub {
public static void main(String[] args) {
ThreadIceCream Th1 = new ThreadIceCream();
ThreadIceCream Th2 = new ThreadIceCream();
} }
Now I want to create 10 Icecreams (i.e. Create 10 instances of the ThreadIceCream class simultaneously) and I want to use threads in Java to do this. I tried a few things but they were no were close.
Well it's not really that hard:
Thread[] threads = new Thread[10];
for(int i = 0; i < 10; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
ThreadIceCream tic = new ThreadIceCream();
}
});
threads[i].start();
}
for(int i = 0; i < 10; i++) {
threads[i].join();
}
Sure, this won't do much because the work performed by each thread is so small that the overhead to start the threads is actually higher, but whatever.
You should also learn to use the ExecutorService for higher efficiency. Pure threads are heavyweight and are rarely a good solution for anything, especially in groups. Here's an ExecutorService version of the above:
ExecutorService exec = Executors.newFixedThreadPool(10);
for(int i = 0; i < 10; i++) {
exec.submit(new Runnable() {
public void run() {
ThreadIceCream tic = new ThreadIceCream();
}
});
}
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
Here we are creating a pool of 10 threads and submitting 10 tasks. The threads are recycled betweeen task executions, so only 10 threads are ever created, no matter how many tasks you submit. Since the tasks are so small several tasks may even be executed on the same thread, but that's actually a good thing.

Categories

Resources