Java reading number of lines in two files while using threads - java

I posted yesterday about this but my code was messy. What I'm looking to do is count the number of lines of two separate files and print the line number in a separate thread for each file.
This is what i have:
import java.io.File;
import java.util.Scanner;
public class fileReader implements Runnable
{
static int count = 0;
static int count1 = 0;
public void run()
{
try
{
Scanner file1 = new Scanner(new File("filetest1.txt"));
Scanner file2 = new Scanner(new File("filetest2.txt"));
while (file1.hasNextLine())
{
count++;
file1.nextLine();
}
while (file2.hasNextLine())
{
count1++;
file2.nextLine();
}
}
catch(Exception e)
{
count = -1;
count1 = -1;
}
}
public static void main(String[] args)
{
(new Thread(new fileReader())).start();
System.out.println("File one has " + count + " lines");
System.out.println("File two has " + count1 + " lines");
}
}
The problem is that it does not work. Can someone point me in the right direction? Thanks.

You are on the right track using Runnable. You have a couple problems right now:
You currently create 1 fileReader with 1 thread for both files, but your intent is to have a separate thread for each.
You are trying to communicate between threads using some static variables, but you're not waiting for the worker thread to be done before printing the variables.
To solve your first problem, you need to create a new Runnable and a new thread for each file. (I'm going to rename your fileReader class to LineCounter to avoid confusion with the similarly named FileReader from the standard library).
class LineCounter implements Runnable {
private final File file;
public LineCounter(File file) {
this.file = file;
}
public void run() {
// Count lines in file.
}
}
Now you can create 2 separate LineCounter objects, one to count the lines in each file.
Thread thread1 = new Thread(new LineCounter(new File("filetest1.txt")));
Thread thread2 = new Thread(new LineCounter(new File("filetest2.txt")));
thread1.start();
thread2.start();
As for your second problem, your main thread must (the one that spawned off these two other threads) needs to wait for them to complete before reading the variables holding the number of lines in each file. You can instruct your main thread to wait for the another thread to complete by using join()
thread1.join();
thread2.join();
// Print your variables.
That being said, communicating between threads with static variables is dubious at best:
To really do this right, you'd have to either synchronize access to those variables, or else declare them as volatile.
When programming with threads, it's preferable to share as little state (variables) as possible with other threads.
Further, there exists the very convenient Executor framework which presents a nicer API for dealing with threads. One big win is that is allows you to easily return a value from a thread, which you could use to return the number of lines read.
The big changes are:
Your class implements Callable<Integer> instead of Runnable. The <Integer> part here means you want your thread to return an Integer (i.e. the number of lines in the file)
Instead of void run(), you define Integer call(), which returns the number of lines in the file.
Instead of creating Threads directly, you submit tasks to be done to an Executor.
Instead of join()ing threads together, simply get() the return value of a thread from a Future.
Converted to Executor style, the solution is something like
class LineCounter implements Callable<Integer> {
private final File file;
public LineCounter(File file) {
this.file = file;
}
public Integer call() {
// Count number of lines in file.
return numLines;
}
}
And in your main thread:
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> future1 = executor.submit(new LineCounter(new File("file1.txt")));
Future<Integer> future2 = executor.submit(new LineCounter(new File("file2.txt")));
Integer file1Lines = future1.get();
Integer file2Lines = future2.get();

You need to wait for the thread to finish its job.
You print your resault too early.
thr.join() blocks your program until thr finishes.
public static void main(String args[]) {
try {
Thread thr = new Thread(new fileReader());
thr.start();
thr.join();
System.out.println("File one has " + count + " lines");
System.out.println("File two has " + count1 + " lines");
} catch (InterruptedException ex) {
Logger.getLogger(fileReader.class.getName()).log(Level.SEVERE, null, ex);
}
}

public class fileReader1 implements Runnable
{
static int count = 0;
public void run()
{
try
{
Scanner file1 = new Scanner(new File("filetest1.txt"));
............
............
............
}
}
public class fileReader2 implements Runnable
{
static int count = 0;
public void run()
{
try
{
Scanner file1 = new Scanner(new File("filetest2.txt"));
............
............
............
}
}
Now you can start two threads and start reading the files simultaneously:
Thread t1=new Thread(new fileReader1());
Thread t2=new Thread(new fileReader2());
t1.start();
t2.start();

Related

Synchronise ArrayList over two threads

I'm having a difficult time understanding how to synchronise an ArrayList over two threads. Basically, I want one thread appending objects to the list and the other one reading from that list at the same time.
Here is the class that deploys the threads:
public class Main {
public static ArrayList<Good> goodList = new ArrayList();
public static void main(String[] args) {
Thread thread1 = new Thread(new GoodCreator());
Thread thread2 = new Thread(new WeightCounter());
thread1.start();
thread2.start();
}
}
Then the two Runnable classes:
This one reads lines of two values from a text file and appends new objects.
public class GoodCreator implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
private static Scanner scan;
#Override
public void run() {
System.out.println("Thread 1 started");
int objCount = 0;
try {
scan = new Scanner(new File(System.getProperty("user.home") + "//Goods.txt"));
} catch (FileNotFoundException e) {
System.out.println("File not found!");
e.printStackTrace();
}
while(scan.hasNextLine()){
String line = scan.nextLine();
String[] words = line.split("\\s+");
synchronized(goodList){
goodList.add(new Good(Integer.parseInt(words[0]), Integer.parseInt(words[1])));
objCount++;
}
if(objCount % 200 == 0) System.out.println("created " + objCount + " objects");
}
}
}
This iterates over the arraylist and is supposed to sum up one of the fields.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
int weightSum = 0;
synchronized(goodList){
for(Good g : goodList){
weightSum += g.getWeight();
}
}
System.out.println(weightSum);
}
}
No matter the input, weightSum never gets incremented and stays 0
Thread 1 started
Thread 2 started
0
Any help is much appreciated
You are running two independently running threads. These thread can run in any order and if one stop e.g. to read from a file, the other thread doesn't assume it has to wait for it.
In short, your second thread completes before the first thread has added anything to the list.
There is no good fix as this is not a good example of why you would use multiple threads, however to get an outcome what you can do is this.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
for(int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
throw AssertionError(ie);
}
int weightSum = 0;
synchronized(goodList){
for (Good g : goodList)
weightSum += g.getWeight();
}
System.out.println(weightSum);
}
}
}
This will print the sum 10 times, 0.1 seconds apart. Depending on how long your file takes to load you will be able to see the sum for what has loaded so far.
This is something called a producer-consumer task. You can do it with arraylist, but it's honestly just not the right way to approach this problem.
Luckily, Java provides us with some collections, the BlockingQueue collections, which are designed specifically for this reason;
//the collection with the stuff in it
static BlockingQueue<Object> items = new BlockingQueue<Object>();
//(there are a few different types of blocking queues, check javadocs.
//you would want Linked or Array blocking queue
//what happens on the reader thread
public void producer()
{
//read the data into the collection
for (all the data in the file)
{
//add the next item
items.put(/* next item from file or w/e */);
//stop if necessary
if (atEndOfFile) stillReadingData = false;
//etc
}
}
Now you need to read the data out of the queue - luckily this is easy enough;
//what happens on the other threads
public void consumer()
{
//keep this thread alive so long as there is data to process
//or so long as there might be more data to process
while (stillReadingData || !items.isEmpty())
{
//get the next item from the list
//while the list is empty, we basically sleep for "timeout" timeunits,
//then the while-loop would repeat, and so on
Object o = items.poll(long timeout, int units);
if (o != null) //process it
}
}
In this way, you can continuously add items to the queue with the producer thread, and the items will be processed as soon as a consumer thread is free (this approach scales well with lots of consumer threads). If you still need a collection for the items, then you should make a second collection and add them to that after they have been processed.
As a side note, you may still need to synchronize oprations which occur while processing the items. For example, you would need to synchronize increments on "weightSum" (or alternately use AtomicInteger).
Try this change in the WeightCounter class.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
int weightSum = 0;
while(goodList.isEmpty()) {
Thread.sleep(1000);
}
synchronized(goodList){
for(Good g : goodList){
weightSum += g.getWeight();
}
}
System.out.println(weightSum);
}
}
This change will cause the WeightCounter thread to wait for the other thread to finish populating the goodList with data before attempting to read from it.

Java asynchronous text input and output

i must say i am a beginner in Java.
I use Eclipse. I want to accomplish the following scenario and couldn't find how to do it:
While a java program runs it outputs text to the console, i also want to be able to input text and process it without blocking the output by waiting for input.
Assume this:
-Thread 1 outputs a number to the console every second
-Thread 2 listens for input
(The code is a mockup)
//**Thread 1:**
int incrementBy = 0;
for (int i = 0; i < 1000; i++) {
i = i + incrementBy;
//Pause for 1 seconds
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("TEXT OUTPUT INTERUPTED");
}
//Print text
System.out.println(i);
}
//**Thread 2:**
String myIncrement = System.console().readLine();
(Now process the input and change the incrementBy var in Thread 1)
Right now in my program i am using 1 thread for input and another one for output. But i can easily change the design.
All i could find was something about server and client, i would like to keep my code in one place-package. And i currently don't know how to make a GUI with a text box for output and one for input.
Can you recommend something please?
SOLVED - it turns out I am VERY VERY new to JAVA.
It seems that java allows the user to input text while another thread outputs to the console.
This is the reason why i couldn't find anything in my searches for things like "java input and output to console asynchronous". I had a problem in my input code exactly where i was asking for input and because i knew from single threaded programs that the program halts until i enter the text and press enter i assumed that the error was thrown because the output thread was taking over the console and terminating the input thread.
Here is my code for those who search (Take it as a guide, might not work if compiled):
//Main app
public class textInpuOutputManager {
//here we create the two threads (objects that implement the runnable interface)
static TextInputObject ti;
static TextOutputObject to;
public static void main(String[] args) {
//we instantiate the objects
ti = new TextInputObject();
to = new TextOutputObject();
//we call the start method to start the threads for input and output
ti.start();
to.start();
}
}
//TextInputObject class
public class TextInputObject implements Runnable {
//Method that gets called when the object is instantiated
public TextInputObject() {
System.out.println("Created TextInputObject");
}
//create a thread object and check if it's not already created
static Thread thread;
//This method gets called from the main
public void start() {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
//this method gets called by the thread.start(); from above
#
Override
public void run() {
System.out.println("Text input thread created and now it runs");
readTextFromConsole();
}
Scanner inputReader = new Scanner(System.in);
//check for input all the time - THIS WILL NOT HALT THE PROGRAM
public void readTextFromConsole() {
System.out.println("Enter something:");
String myinput = inputReader.nextLine();
System.out.println("You Entered: " + myinput);
readTextFromConsole();
}
}
//TextOutputObject
public class TextOutputObject implements Runnable {
//Method that gets called when the object is instantiated
public TextOutputObject() {
System.out.println("Created TextOutputObject");
}
static Thread thread;
public void start() {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
#
Override
public void run() {
System.out.println("Text output thread created and now it runs");
//Make it output text every 4 seconds to test if you can input text while it's used for output
for (int i = 0; i < 100; i++) {
//Pause for 4 seconds
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
System.out.println("TEXT OUTPUT INTERUPTED");
}
//Print i to console
System.out.println(i);
}
}
}
Also BIG thank you for all of you who took the time to respond
I'm not sure exactly what it is you want to do, but if you're new and you don't know how to make guis, I would try a JOptionPane
String input = JOptionPane.showInputDialog("User input is returned as a string; use Integer.parseInt(input) to retrieve an integer from this method");
You could make two inner classes and implement Runnable in both of them.
import java.util.Scanner;
public class Test{
private Thread t1;
private Thread t2;
public static void main(String[] args){
new Test();
}
private class TOne implements Runnable{
public void run(){
int incrementBy = 0;
for (int i = 0; i < 1000; i++) {
i = i + incrementBy;
//Pause for 1 seconds
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("TEXT OUTPUT INTERUPTED");
}
//Print text
System.out.println(i);
}
}
}
private class TTwo implements Runnable{
public void run(){//Code for Thread 2
try{
Scanner scr = new Scanner(System.in);
System.out.println(scr.next());
}catch(Exception ex){
ex.printStackTrace();
}
}
}
public Test(){
t1 = new Thread(new TOne());
t1.run();
t2 = new Thread(new TTwo());
t2.run();
}
}
Not the most elegant way, and it doesn't work flawlessly. You'd have to tinker with the second Thread a little more. For information on how GUI etc. work you should check the Swing library. Googling it should work just fine.
Some important keywords for you wpuld be:
JFrame, JPanel, LayoutManager, JTextArea, JTextField, JButton, ActionListener, Inner Class

How do I adjust this for single/multithreaded?

I have a class that basically has two methods the first one takes a String (name of a file) and a thread:
public static void readFile(String s, Thread t){
Runnable read = new Runnable() {
public void run() {
//SOME CODE
}
t = new Thread(read);
t.start();
}
The second method is a main method that asks the user for input and then uses that input to set a few things (like if the number of threads is just one or if it is equal to the number of objects in a list).
public static void main(String[] args){
//SOME CODE
for(Object x: ListOfObjects){
//t1 is the same thread each time if one thread requested, otherwise t1 is a different thread each time
readFromFile(textFileString, t1);
//SOME CODE
}
If the user were to request 5 threads (for 5 items in a list), how could the above be modified for that? Currently, my main method has a loop (for the number of items in the list) and then the first method is called for each iteration in the loop. Is there a way to take the number of threads requested by the user, and initiate/start them in the first method all at once instead of one at a time and calling the method?
Implement the Runnable interface. I tried
this and it seems to work:
class StringThread implements Runnable
{
private String str;
private int num;
StringThread(String s, int n)
{
str = new String (s);
num =n;
}
public void run ( )
{
for (int i=1; i<=num; i++)
System.out.print ("THREAD NAMED: " + str+" I IS: " +
i + "\n");
}
}
//IN the main program:
StringThread t1 = new StringThread ("THR-1",100);
new Thread(t1). start ( );
StringThread t2 = new StringThread ("THR-2",200);
new Thread(t2). start ( );

Wait for one of several threads

I have a java application where the main-thread starts 2 other threads.
If one of these threads terminates, the main-thread may start another thread depending on the result of the terminated thread.
Example:
The main-thread creates 2 threads: A and B. Thread A will load a picture and thread B will load another picture. If A terminates and loaded the picture successfully a new Thread C will be created which does some other stuff and so on.
How can i do this? I do not want to use busy waiting in the main thread and check every 100ms if one of the two threads has finished.
I think i cannot use a thread pool because the number of active threads (in this case A and B) will vary extremely and it's the main-threads dicision to create a new thread or not.
This is rough sketch of the "busy waiting" solution:
public class TestThreads {
private class MyThread extends Thread {
volatile boolean done = false;
int steps;
#Override
public void run() {
for (int i=0; i<steps; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException exc) { }
}
done = true;
synchronized (this) {
notify();
}
}
public void waitFor(long ms) {
synchronized (this) {
try {
wait(ms);
} catch (InterruptedException exc) { }
}
}
}
public void startTest() {
MyThread a = new MyThread();
a.steps = 6;
a.start();
MyThread b = new MyThread();
b.steps = 3;
b.start();
while (true) {
if (!a.done) {
a.waitFor(100);
if (a.done) {
System.out.println("C will be started, because A is done.");
}
}
if (!b.done) {
b.waitFor(100);
if (b.done) {
System.out.println("C will be started, because B is done.");
}
}
if (a.done && b.done) {
break;
}
}
}
public static void main(String[] args) {
TestThreads test = new TestThreads();
test.startTest();
}
}
This sounds like a classic case for using a ThreadPoolExecutor for performing the tasks concurrently, and wrapping it with an ExecutorCompletionService, for collecting the results as they arrive.
For example, assuming that tasks contains a set of tasks to execute in parallel, each returning a String value when it terminates, the code to process the results as they become available can be something like:
List<Callable<String>> tasks = ....;
Executor ex = Executors.newFixedThreadPool(10);
ExecutorCompletionService<String> ecs = new ExecutorCompletionService<String>(ex);
for (Callable<String> task : tasks)
ecs.submit(task);
for(int i = 0; i < tasks.size(); i++) {
String result = ecs.take().get();
//Do something with result
}
If you include the identity of the task as a part of the returned value, then you can make decisions depending on the completion order.
Check Semaphore
A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it
So, whenever you thread finishes, it frees one permit, which is then acquired by the main thread
You should use a thread pool. In a thread pool, you have a fixed number of threads and tasks are kept in a queue; whenever a thread is available, a task is taken off the queue and executed by that thread.
Here is a link to the Sun tutorial on thread pooling.
Edit: just noticed that you wrote in your answer that you think you cannot use thread pooling. I don't see why this is the case. You can set threads to be created on-demand rather than all at once if you are worried about creation overhead, and once created an idle thread is not really going to hurt anything.
You also say that it's the main thread's decision to create a new Thread or not, but does it really need to be? I think that may just overcomplicate things for you.
Is there a reason to control the thread execution directly instead of using something like
ExecutorService?
#danben got there first, but I fell into the same pooling trap.
A lot of the complexity in your code is that the main thread is trying to wait on two different objects. There's nothing which says you can't use wait and notify on another object, and if your tasks are ( A or B ) then C, the code below will work - wait on a reference which is set to indicate the first task to complete.
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class BiggieThreads
{
private static class MyTask implements Runnable
{
final int steps;
final AtomicReference<MyTask> shared;
final String name;
MyTask ( int steps, AtomicReference<MyTask> shared, String name )
{
this.shared = shared;
this.steps = steps;
this.name = name;
}
#Override
public void run()
{
for ( int i = 1; i <= steps; i++ ) {
System.out.println ( "Running: " + this + " " + i + "/" + steps);
try {
Thread.sleep ( 100 );
} catch ( InterruptedException exc ) { }
}
// notify if this is the first to complete
if ( shared.compareAndSet ( null, this ) )
synchronized ( shared ) {
shared.notify();
}
System.out.println ( "Completed: " + this );
}
#Override
public String toString ()
{
return name;
}
}
public void startTest() throws InterruptedException
{
final ExecutorService pool = Executors.newFixedThreadPool ( 3 );
final AtomicReference<MyTask> shared = new AtomicReference<MyTask>();
Random random = new Random();
synchronized ( shared ) {
// tasks launched while lock on shared held to prevent
// them notifying before this thread waits
pool.execute ( new MyTask ( random.nextInt ( 5 ) + 3, shared, "a" ) );
pool.execute ( new MyTask ( random.nextInt ( 5 ) + 3, shared, "b" ) );
shared.wait();
}
System.out.println ( "Reported: " + shared.get() );
pool.shutdown();
}
public static void main ( String[] args ) throws InterruptedException
{
BiggieThreads test = new BiggieThreads ();
test.startTest();
}
}
I'd tend to use a semaphore for this job in production, as although the wait is quite simple, using in semaphore puts a name to the behaviour, so there's less to work out when you next read the code.

How to wait for a number of threads to complete?

What is a way to simply wait for all threaded process to finish? For example, let's say I have:
public class DoSomethingInAThread implements Runnable{
public static void main(String[] args) {
for (int n=0; n<1000; n++) {
Thread t = new Thread(new DoSomethingInAThread());
t.start();
}
// wait for all threads' run() methods to complete before continuing
}
public void run() {
// do something here
}
}
How do I alter this so the main() method pauses at the comment until all threads' run() methods exit? Thanks!
You put all threads in an array, start them all, and then have a loop
for(i = 0; i < threads.length; i++)
threads[i].join();
Each join will block until the respective thread has completed. Threads may complete in a different order than you joining them, but that's not a problem: when the loop exits, all threads are completed.
One way would be to make a List of Threads, create and launch each thread, while adding it to the list. Once everything is launched, loop back through the list and call join() on each one. It doesn't matter what order the threads finish executing in, all you need to know is that by the time that second loop finishes executing, every thread will have completed.
A better approach is to use an ExecutorService and its associated methods:
List<Callable> callables = ... // assemble list of Callables here
// Like Runnable but can return a value
ExecutorService execSvc = Executors.newCachedThreadPool();
List<Future<?>> results = execSvc.invokeAll(callables);
// Note: You may not care about the return values, in which case don't
// bother saving them
Using an ExecutorService (and all of the new stuff from Java 5's concurrency utilities) is incredibly flexible, and the above example barely even scratches the surface.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class DoSomethingInAThread implements Runnable
{
public static void main(String[] args) throws ExecutionException, InterruptedException
{
//limit the number of actual threads
int poolSize = 10;
ExecutorService service = Executors.newFixedThreadPool(poolSize);
List<Future<Runnable>> futures = new ArrayList<Future<Runnable>>();
for (int n = 0; n < 1000; n++)
{
Future f = service.submit(new DoSomethingInAThread());
futures.add(f);
}
// wait for all tasks to complete before continuing
for (Future<Runnable> f : futures)
{
f.get();
}
//shut down the executor service so that this thread can exit
service.shutdownNow();
}
public void run()
{
// do something here
}
}
instead of join(), which is an old API, you can use CountDownLatch. I have modified your code as below to fulfil your requirement.
import java.util.concurrent.*;
class DoSomethingInAThread implements Runnable{
CountDownLatch latch;
public DoSomethingInAThread(CountDownLatch latch){
this.latch = latch;
}
public void run() {
try{
System.out.println("Do some thing");
latch.countDown();
}catch(Exception err){
err.printStackTrace();
}
}
}
public class CountDownLatchDemo {
public static void main(String[] args) {
try{
CountDownLatch latch = new CountDownLatch(1000);
for (int n=0; n<1000; n++) {
Thread t = new Thread(new DoSomethingInAThread(latch));
t.start();
}
latch.await();
System.out.println("In Main thread after completion of 1000 threads");
}catch(Exception err){
err.printStackTrace();
}
}
}
Explanation:
CountDownLatch has been initialized with given count 1000 as per your requirement.
Each worker thread DoSomethingInAThread will decrement the CountDownLatch, which has been passed in constructor.
Main thread CountDownLatchDemo await() till the count has become zero. Once the count has become zero, you will get below line in output.
In Main thread after completion of 1000 threads
More info from oracle documentation page
public void await()
throws InterruptedException
Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted.
Refer to related SE question for other options:
wait until all threads finish their work in java
Avoid the Thread class altogether and instead use the higher abstractions provided in java.util.concurrent
The ExecutorService class provides the method invokeAll that seems to do just what you want.
Consider using java.util.concurrent.CountDownLatch. Examples in javadocs
Depending on your needs, you may also want to check out the classes CountDownLatch and CyclicBarrier in the java.util.concurrent package. They can be useful if you want your threads to wait for each other, or if you want more fine-grained control over the way your threads execute (e.g., waiting in their internal execution for another thread to set some state). You could also use a CountDownLatch to signal all of your threads to start at the same time, instead of starting them one by one as you iterate through your loop. The standard API docs have an example of this, plus using another CountDownLatch to wait for all threads to complete their execution.
As Martin K suggested java.util.concurrent.CountDownLatch seems to be a better solution for this. Just adding an example for the same
public class CountDownLatchDemo
{
public static void main (String[] args)
{
int noOfThreads = 5;
// Declare the count down latch based on the number of threads you need
// to wait on
final CountDownLatch executionCompleted = new CountDownLatch(noOfThreads);
for (int i = 0; i < noOfThreads; i++)
{
new Thread()
{
#Override
public void run ()
{
System.out.println("I am executed by :" + Thread.currentThread().getName());
try
{
// Dummy sleep
Thread.sleep(3000);
// One thread has completed its job
executionCompleted.countDown();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
try
{
// Wait till the count down latch opens.In the given case till five
// times countDown method is invoked
executionCompleted.await();
System.out.println("All over");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
If you make a list of the threads, you can loop through them and .join() against each, and your loop will finish when all the threads have. I haven't tried it though.
http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join()
Create the thread object inside the first for loop.
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
// some code to run in parallel
}
});
threads[i].start();
}
And then so what everyone here is saying.
for(i = 0; i < threads.length; i++)
threads[i].join();
You can do it with the Object "ThreadGroup" and its parameter activeCount:
As an alternative to CountDownLatch you can also use CyclicBarrier e.g.
public class ThreadWaitEx {
static CyclicBarrier barrier = new CyclicBarrier(100, new Runnable(){
public void run(){
System.out.println("clean up job after all tasks are done.");
}
});
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Thread t = new Thread(new MyCallable(barrier));
t.start();
}
}
}
class MyCallable implements Runnable{
private CyclicBarrier b = null;
public MyCallable(CyclicBarrier b){
this.b = b;
}
#Override
public void run(){
try {
//do something
System.out.println(Thread.currentThread().getName()+" is waiting for barrier after completing his job.");
b.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
To use CyclicBarrier in this case barrier.await() should be the last statement i.e. when your thread is done with its job. CyclicBarrier can be used again with its reset() method. To quote javadocs:
A CyclicBarrier supports an optional Runnable command that is run once per barrier point, after the last thread in the party arrives, but before any threads are released. This barrier action is useful for updating shared-state before any of the parties continue.
The join() was not helpful to me. see this sample in Kotlin:
val timeInMillis = System.currentTimeMillis()
ThreadUtils.startNewThread(Runnable {
for (i in 1..5) {
val t = Thread(Runnable {
Thread.sleep(50)
var a = i
kotlin.io.println(Thread.currentThread().name + "|" + "a=$a")
Thread.sleep(200)
for (j in 1..5) {
a *= j
Thread.sleep(100)
kotlin.io.println(Thread.currentThread().name + "|" + "$a*$j=$a")
}
kotlin.io.println(Thread.currentThread().name + "|TaskDurationInMillis = " + (System.currentTimeMillis() - timeInMillis))
})
t.start()
}
})
The result:
Thread-5|a=5
Thread-1|a=1
Thread-3|a=3
Thread-2|a=2
Thread-4|a=4
Thread-2|2*1=2
Thread-3|3*1=3
Thread-1|1*1=1
Thread-5|5*1=5
Thread-4|4*1=4
Thread-1|2*2=2
Thread-5|10*2=10
Thread-3|6*2=6
Thread-4|8*2=8
Thread-2|4*2=4
Thread-3|18*3=18
Thread-1|6*3=6
Thread-5|30*3=30
Thread-2|12*3=12
Thread-4|24*3=24
Thread-4|96*4=96
Thread-2|48*4=48
Thread-5|120*4=120
Thread-1|24*4=24
Thread-3|72*4=72
Thread-5|600*5=600
Thread-4|480*5=480
Thread-3|360*5=360
Thread-1|120*5=120
Thread-2|240*5=240
Thread-1|TaskDurationInMillis = 765
Thread-3|TaskDurationInMillis = 765
Thread-4|TaskDurationInMillis = 765
Thread-5|TaskDurationInMillis = 765
Thread-2|TaskDurationInMillis = 765
Now let me use the join() for threads:
val timeInMillis = System.currentTimeMillis()
ThreadUtils.startNewThread(Runnable {
for (i in 1..5) {
val t = Thread(Runnable {
Thread.sleep(50)
var a = i
kotlin.io.println(Thread.currentThread().name + "|" + "a=$a")
Thread.sleep(200)
for (j in 1..5) {
a *= j
Thread.sleep(100)
kotlin.io.println(Thread.currentThread().name + "|" + "$a*$j=$a")
}
kotlin.io.println(Thread.currentThread().name + "|TaskDurationInMillis = " + (System.currentTimeMillis() - timeInMillis))
})
t.start()
t.join()
}
})
And the result:
Thread-1|a=1
Thread-1|1*1=1
Thread-1|2*2=2
Thread-1|6*3=6
Thread-1|24*4=24
Thread-1|120*5=120
Thread-1|TaskDurationInMillis = 815
Thread-2|a=2
Thread-2|2*1=2
Thread-2|4*2=4
Thread-2|12*3=12
Thread-2|48*4=48
Thread-2|240*5=240
Thread-2|TaskDurationInMillis = 1568
Thread-3|a=3
Thread-3|3*1=3
Thread-3|6*2=6
Thread-3|18*3=18
Thread-3|72*4=72
Thread-3|360*5=360
Thread-3|TaskDurationInMillis = 2323
Thread-4|a=4
Thread-4|4*1=4
Thread-4|8*2=8
Thread-4|24*3=24
Thread-4|96*4=96
Thread-4|480*5=480
Thread-4|TaskDurationInMillis = 3078
Thread-5|a=5
Thread-5|5*1=5
Thread-5|10*2=10
Thread-5|30*3=30
Thread-5|120*4=120
Thread-5|600*5=600
Thread-5|TaskDurationInMillis = 3833
As it's clear when we use the join:
The threads are running sequentially.
The first sample takes 765 Milliseconds while the second sample takes 3833 Milliseconds.
Our solution to prevent blocking other threads was creating an ArrayList:
val threads = ArrayList<Thread>()
Now when we want to start a new thread we most add it to the ArrayList:
addThreadToArray(
ThreadUtils.startNewThread(Runnable {
...
})
)
The addThreadToArray function:
#Synchronized
fun addThreadToArray(th: Thread) {
threads.add(th)
}
The startNewThread funstion:
fun startNewThread(runnable: Runnable) : Thread {
val th = Thread(runnable)
th.isDaemon = false
th.priority = Thread.MAX_PRIORITY
th.start()
return th
}
Check the completion of the threads as below everywhere it's needed:
val notAliveThreads = ArrayList<Thread>()
for (t in threads)
if (!t.isAlive)
notAliveThreads.add(t)
threads.removeAll(notAliveThreads)
if (threads.size == 0){
// The size is 0 -> there is no alive threads.
}
The problem with:
for(i = 0; i < threads.length; i++)
threads[i].join();
...is, that threads[i + 1] never can join before threads[i].
Except the "latch"ed ones, all solutions have this lack.
No one here (yet) mentioned ExecutorCompletionService, it allows to join threads/tasks according to their completion order:
public class ExecutorCompletionService<V>
extends Object
implements CompletionService<V>
A CompletionService that uses a supplied Executor to execute tasks. This class arranges that submitted tasks are, upon completion, placed on a queue accessible using take. The class is lightweight enough to be suitable for transient use when processing groups of tasks.
Usage Examples.
Suppose you have a set of solvers for a certain problem, each returning a value of some type Result, and would like to run them concurrently, processing the results of each of them that return a non-null value, in some method use(Result r). You could write this as:
void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException, ExecutionException {
CompletionService<Result> cs = new ExecutorCompletionService<>(e);
solvers.forEach(cs::submit);
for (int i = solvers.size(); i > 0; i--) {
Result r = cs.take().get();
if (r != null)
use(r);
}
}
Suppose instead that you would like to use the first non-null result of the set of tasks, ignoring any that encounter exceptions, and cancelling all other tasks when the first one is ready:
void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException {
CompletionService<Result> cs = new ExecutorCompletionService<>(e);
int n = solvers.size();
List<Future<Result>> futures = new ArrayList<>(n);
Result result = null;
try {
solvers.forEach(solver -> futures.add(cs.submit(solver)));
for (int i = n; i > 0; i--) {
try {
Result r = cs.take().get();
if (r != null) {
result = r;
break;
}
} catch (ExecutionException ignore) {}
}
} finally {
futures.forEach(future -> future.cancel(true));
}
if (result != null)
use(result);
}
Since: 1.5 (!)
Assuming use(r) (of Example 1) also asynchronous, we had a big advantage. #

Categories

Resources