reading a parsing messages in a thread - java

Forgive me if the title is a bit vague. I will try to explain a bit better what i am trying to accomplish.
There is a function called parsebytes that is part of an external interface that i have implemented. It takes an array of bytes and a length. All parsing in this particular program runs on a single thread so i want to get my data out of parsebytes as quickly as possible so it can return to getting more data off the line. My methodology in pseudocode is this:
Create an externally running thread (ParserThreadClass).
every time parsebytes is called, put the bytes into a queue in the ParserThreadClass by looping through all the bytes and doing a byteQueue.add(bytes[i]). This code is surrounded by a synchronized(byteQueue)
That, in effect, should free the parsebytes to go back and get more data.
While that is happening, my ParserThreadClass is also running. This is the code in the run() function
while (!shutdown) //while the thread is still running
{
synchronized (byteQueue)
{
bytes.addAll(byteQueue); //an arraylist
byteQueue.clear();
}
parseMessage(); //this will take the bytes arraylist and build an xml message.
}
Am i being overly inefficient here? If so, can someone give me an idea of how i should tackle this?

This is how I've tried to solve the problem previously. Basically you have a producer thread, like you have here, that reads the file and puts items onto the queue. Then you have a worker thread that reads things from the queue and processes them. Code is below, but it looks essentially the same as what you're doing. What I found is that this gives me just about no speed up, because the processing I need to do per line is pretty quick, relative to the disk read. If the parsing you have to do is pretty intensive, or the chunks are pretty large, you could see some speed up doing it this way. But if it's pretty minimal, don't expect to see much in the way of performance improvement, because the process is IO bound. In those situations, you need to parallelize the disk access, which you can't really do on a single machine.
public static LinkedBlockingQueue<Pair<String, String>> mappings;
public static final Pair<String, String> end =
new Pair<String, String>("END", "END");
public static AtomicBoolean done;
public static NpToEntityMapping mapping;
public static Set<String> attested_nps;
public static Set<Entity> possible_entities;
public static class ProducerThread implements Runnable {
private File f;
public ProducerThread(File f) {
this.f = f;
}
public void run() {
try {
BufferedReader reader = new BufferedReader(new FileReader(f));
String line;
while ((line = reader.readLine()) != null) {
String entities = reader.readLine();
String np = line.trim();
mappings.put(new Pair<String, String>(np, entities));
}
reader.close();
for (int i=0; i<num_threads; i++) {
mappings.put(end);
}
} catch (InterruptedException e) {
System.out.println("Producer thread interrupted");
} catch (IOException e) {
System.out.println("Producer thread threw IOException");
}
}
}
public static class WorkerThread implements Runnable {
private Dictionary dict;
private EntityFactory factory;
public WorkerThread(Dictionary dict, EntityFactory factory) {
this.dict = dict;
this.factory = factory;
}
public void run() {
try {
while (!done.get()) {
Pair<String, String> np_ent = mappings.take();
if (np_ent == end) {
done.set(false);
continue;
}
String entities = np_ent.getRight();
String np = np_ent.getLeft().toLowerCase();
if (attested_nps == null || attested_nps.contains(np)) {
int np_index = dict.getIndex(np);
HashSet<Entity> entity_set = new HashSet<Entity>();
for (String entity : entities.split(", ")) {
Entity e = factory.createEntity(entity.trim());
if (possible_entities != null) {
possible_entities.add(e);
}
entity_set.add(e);
}
mapping.put(np_index, entity_set);
}
}
} catch (InterruptedException e) {
System.out.println("Worker thread interrupted");
}
}
}
EDIT:
Here's code for the main thread that starts the producer and worker threads:
Thread producer = new Thread(new ProducerThread(f), "Producer");
producer.start();
ArrayList<Thread> workers = new ArrayList<Thread>();
for (int i=0; i<num_threads; i++) {
workers.add(new Thread(new WorkerThread(dict, factory), "Worker"));
}
for (Thread t : workers) {
t.start();
}
try {
producer.join();
for (Thread t : workers) {
t.join();
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted...");
}
It should also be fine to have the work done in the producer thread just be done in the main thread, taking out the need to start and join with another thread in the main code. Be sure to start the worker threads before going through the file, though, and join with them after you've done the work. I'm not sure about the performance differences between that way and the way I have here, though.

Related

Should Thread.sleep be used when reading from a FIFO?

Due to the fact that in almost every question regarding the use of Thread.sleep it is mostly indicated to use it only in certain situations, I come to ask you if it is correct to use it in my case or if there is a better way to do it.
The operating system is Linux(Debian), in which a bash script is running that is detecting when a device (more specifically, a storage device) is inserted/removed, and then writes into a FIFO a string under the type "ADD {path-to-dev}" or "REM {path-to-dev}".
I created a small app in java which makes use of two threads. The first thread will call upon a read method that parses the String to the standard output, after which it will wait(). The second thread will check if the FIFO is empty or not and then, when it sees that a String has been inserted then it will call notify() so the other thread will print the String in there and so on. Inside the loop where it checks if the FIFO has data or not, I call Thread.sleep(1000), and I am unsure whether this is a good approach or not. I will present the code which handles all the action.
First, the class which has the methods of reading:
public class Detect {
private File file;
private BufferedReader read;
private volatile boolean readable;
private static String readFromFile;
public Detect() throws FileNotFoundException {
file = new File("/hardware_stuff/hardware_events");
read = new BufferedReader(new FileReader(file));
readable = true;
}
synchronized String readFromFifo() {
while (!readable) {
try {
wait();
} catch (InterruptedException ex) {
System.out.println("Interrupted during the wait for read.");
}
}
try {
while (read.ready()) {
readFromFile = read.readLine();
}
} catch (IOException ex) {
System.out.println("Error in reading from FIFO.");
}
readable = false;
notify();
return readFromFile;
}
synchronized void waitForFifo() {
while (readable) {
try {
wait();
} catch (InterruptedException ex) {
Logger.getLogger(Detect.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
while (!read.ready()) {
Thread.sleep(1000);
System.out.println("Sleeping due to lack of activity in FIFO in thread : " + Thread.currentThread().getName());
}
} catch (IOException | InterruptedException ex) {
Logger.getLogger(Detect.class.getName()).log(Level.SEVERE, null, ex);
}
readable = true;
notify();
}}
Next, the thread which will read from it.
public class ReadThread extends Thread {
Detect detect;
private boolean shouldBeRunning;
public ReadThread(Detect detect) {
this.detect = detect;
shouldBeRunning = true;
}
#Override
public void run() {
while (shouldBeRunning) {
String added = detect.readFromFifo();
System.out.println(added);
}
}
public void stopRunning() {
shouldBeRunning = false;
}}
Finally, the thread which will check if the FIFO is empty or not.
public class NotifyThread extends Thread {
Detect detect;
private boolean shouldBeRunning;
public NotifyThread(Detect detect) {
this.detect = detect;
shouldBeRunning = true;
}
#Override
public void run() {
while (shouldBeRunning) {
detect.waitForFifo();
}
}
public void stopRunning() {
shouldBeRunning = false;
}}
In main I just create the threads and start them.
Detect detect = new Detect();
NotifyThread nThread = new NotifyThread(detect);
ReadThread rThread = new ReadThread(detect);
nThread.start();
System.out.println("Started the notifier thread in : " + Thread.currentThread().getName());
rThread.start();
System.out.println("Started the reading thread in : " + Thread.currentThread().getName());
Is there any alternative to calling sleep or another approach I can take to replace the sleep with something else? I have already read other questions related to this topic and I am still uncertain/have not understood whether this sort of case is indicated for sleep or not.
UPDATE: As #james large said, there was no need to poll for ready. I was not aware that if there is no line, the readLine() will 'sleep' and there was no need to poll it after all. I removed the notifier thread, and I simply kept the ReadThread which will call the Detect readFromFifo() method and it all works good. #dumptruckman, thanks for the suggestion. Although it doesn't apply to my case, I didn't know of the WatchService and it was a good read, good stuff to know. #Nyamiou The Galeanthrope, the timer would have been useful, but as I already said, I only keep one thread to execute the same method and it works as intended.#Krzysztof Cichocki, thanks for pointing out there are issues. I was aware of that, otherwise I wouldn't have asked this question.

Unit testing asynchronous computation that has to be interrupted manually

I have got a class that records eyetracking data asynchronously. There are methods to start and stop the recording process. The data is collected in a collection and the collection can only be accessed if the recording thread has finished its work. It basically encapsulates all the threading and synchronizing so the user of my library doesn't have to do it.
The heavily shortened code (generics and error handling omitted):
public class Recorder {
private Collection accumulatorCollection;
private Thread recordingThread;
private class RecordingRunnable implements Runnable {
...
public void run() {
while(!Thread.currentThread().isInterrupted()) {
// fetch data and collect it in the accumulator
synchronized(acc) { acc.add(Eyetracker.getData()) }
}
}
}
public void start() {
accumulatorCollection = new Collection();
recordingThread = new Thread(new RecordingRunnable(accumulatorCollection));
recordingThread.start();
}
public void stop() {
recordingThread.interrupt();
}
public void getData() {
try {
recordingThread.join(2000);
if(recordingThread.isAlive()) { throw Exception(); }
}
catch(InterruptedException e) { ... }
synchronized(accumulatorCollection) { return accumulatorCollection; }
}
}
The usage is quite simple:
recorder.start();
...
recorder.stop();
Collection data = recorder.getData();
My problem with the whole thing is how to test it. Currently i am doing it like this:
recorder.start();
Thread.sleep(50);
recorder.stop();
Collection data = recorder.getData();
assert(stuff);
This works, but it is non-deterministic and slows down the test suite quite a bit (i marked these tests as integration tests, so they have to be run separately to circumvent this problem).
Is there a better way?
There is a better way using a CountDownLatch.
The non-deterministic part of the test stems from two variables in time you do not account for:
creating and starting a thread takes time and the thread may not have started executing the runnable when Thread.start() returns (the runnable will get executed, but it may be a bit later).
the stop/interrupt will break the while-loop in the Runnable but not immediately, it may be a bit later.
This is where a CountDownLatch comes in: it gives you precise information about where another thread is in execution. E.g. let the first thread wait on the latch, while the second "counts down" the latch as last statement within a runnable and now the first thread knows that the runnable finished. The CountDownLatch also acts as a synchronizer: whatever the second thread was writing to memory, can now be read by the first thread.
Instead of using an interrupt, you can also use a volatile boolean. Any thread reading the volatile variable is guaranteed to see the last value set by any other thread.
A CountDownLatch can also be given a timeout which is useful for tests that can hang: if you have to wait to long you can abort the whole test (e.g. shutdown executors, interrupt threads) and throw an AssertionError. In the code below I re-used the timeout to wait for a certain amount of data to collect instead of 'sleeping'.
As an optimization, use an Executor (ThreadPool) instead of creating and starting threads. The latter is relative expensive, using an Executor can really make a difference.
Below the updated code, I made it runnable as an application (main method). (edit 28/02/17: check maxCollect > 0 in while-loop)
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
public class Recorder {
private final ExecutorService executor;
private Thread recordingThread;
private volatile boolean stopRecording;
private CountDownLatch finishedRecording;
private Collection<Object> eyeData;
private int maxCollect;
private final AtomicBoolean started = new AtomicBoolean();
private final AtomicBoolean stopped = new AtomicBoolean();
public Recorder() {
this(null);
}
public Recorder(ExecutorService executor) {
this.executor = executor;
}
public Recorder maxCollect(int max) { maxCollect = max; return this; }
private class RecordingRunnable implements Runnable {
#Override public void run() {
try {
int collected = 0;
while (!stopRecording) {
eyeData.add(EyeTracker.getData());
if (maxCollect > 0 && ++collected >= maxCollect) {
stopRecording = true;
}
}
} finally {
finishedRecording.countDown();
}
}
}
public Recorder start() {
if (!started.compareAndSet(false, true)) {
throw new IllegalStateException("already started");
}
stopRecording = false;
finishedRecording = new CountDownLatch(1);
eyeData = new ArrayList<Object>();
// the RecordingRunnable created below will see the values assigned above ('happens before relationship')
if (executor == null) {
recordingThread = new Thread(new RecordingRunnable());
recordingThread.start();
} else {
executor.execute(new RecordingRunnable());
}
return this;
}
public Collection<Object> getData(long timeout, TimeUnit tunit) {
if (started.get() == false) {
throw new IllegalStateException("start first");
}
if (!stopped.compareAndSet(false, true)) {
throw new IllegalStateException("data already fetched");
}
if (maxCollect <= 0) {
stopRecording = true;
}
boolean recordingStopped = false;
try {
// this establishes a 'happens before relationship'
// all updates to eyeData are now visible in this thread.
recordingStopped = finishedRecording.await(timeout, tunit);
} catch(InterruptedException e) {
throw new RuntimeException("interrupted", e);
} finally {
stopRecording = true;
}
// if recording did not stop, do not return the eyeData (could stil be modified by recording-runnable).
if (!recordingStopped) {
throw new RuntimeException("recording");
}
// only when everything is OK this recorder instance can be re-used
started.set(false);
stopped.set(false);
return eyeData;
}
public static class EyeTracker {
public static Object getData() {
try { Thread.sleep(1); } catch (Exception ignored) {}
return new Object();
}
}
public static void main(String[] args) {
System.out.println("Starting.");
ExecutorService exe = Executors.newSingleThreadExecutor();
try {
Recorder r = new Recorder(exe).maxCollect(50).start();
int dsize = r.getData(2000, TimeUnit.MILLISECONDS).size();
System.out.println("Collected " + dsize);
r.maxCollect(100).start();
dsize = r.getData(2000, TimeUnit.MILLISECONDS).size();
System.out.println("Collected " + dsize);
r.maxCollect(0).start();
Thread.sleep(100);
dsize = r.getData(2000, TimeUnit.MILLISECONDS).size();
System.out.println("Collected " + dsize);
} catch (Exception e) {
e.printStackTrace();
} finally {
exe.shutdownNow();
System.out.println("Done.");
}
}
}
Happy coding :)

Java Multi thread messaging

I have an app with two threads, 1 that writes to a queue and the second one that read async from it.
I need to create a third one that generate 20 more.
the newly created threads will run till explicitly stopped. those 20 threads should get "live" data in order to analyze it.
each of the 20 has a unique ID/name. I need to send the relevant data (that the READ thread collect) to the correct thread (of the 20 threads). e.g. if the data include a string with id (in it) of 2 --> I need to send it to thread with the ID =2.
my question is: how should I hold a "pointer" to each of the 20 threads and send it the relevant data? (I can search the id in a runnable list (that will hold the threads)--> but then I need to call to a method "NewData(string)" in order to send the data to the running thread).
How should I do it?
TIA
Paz
You would probably be better to use a Queue to communicate with your threads. You could then put all of the queues in a map for easy access. I would recommend a BlockingQueue.
public class Test {
// Special stop message to tell the worker to stop.
public static final Message Stop = new Message("Stop!");
static class Message {
final String msg;
// A message to a worker.
public Message(String msg) {
this.msg = msg;
}
public String toString() {
return msg;
}
}
class Worker implements Runnable {
private volatile boolean stop = false;
private final BlockingQueue<Message> workQueue;
public Worker(BlockingQueue<Message> workQueue) {
this.workQueue = workQueue;
}
#Override
public void run() {
while (!stop) {
try {
Message msg = workQueue.poll(10, TimeUnit.SECONDS);
// Handle the message ...
System.out.println("Worker " + Thread.currentThread().getName() + " got message " + msg);
// Is it my special stop message.
if (msg == Stop) {
stop = true;
}
} catch (InterruptedException ex) {
// Just stop on interrupt.
stop = true;
}
}
}
}
Map<Integer, BlockingQueue<Message>> queues = new HashMap<>();
public void test() throws InterruptedException {
// Keep track of my threads.
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 20; i++) {
// Make the queue for it.
BlockingQueue<Message> queue = new ArrayBlockingQueue(10);
// Build its thread, handing it the queue to use.
Thread thread = new Thread(new Worker(queue), "Worker-" + i);
threads.add(thread);
// Store the queue in the map.
queues.put(i, queue);
// Start the process.
thread.start();
}
// Test one.
queues.get(5).put(new Message("Hello"));
// Close down.
for (BlockingQueue<Message> q : queues.values()) {
// Stop each queue.
q.put(Stop);
}
// Join all threads to wait for them to finish.
for (Thread t : threads) {
t.join();
}
}
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}

Java: notify main class when all threads in threadpool are finished / same instance of object in different threads

How do I notify my main class which instantiates a ThreadPoolExecutor when all threads within the ThreadPoolExecutor are completed?
ThreadPoolExecutor threadPool = null;
ThreadClass threadclass1;
ThreadClass threadclass2;
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(maxPoolSize);
puclic MyClass(){
threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue);
threadClass1 = new ThreadClass;
threadClass2 = new ThreadClass;
threadPool.execute(threadClass1);
threadPool.execute(threadClass2);
//Now I would like to do something until the threadPool is done working
//The threads fill a ConcurrentLinkedQueueand I would like to poll
//the queue as it gets filled by the threads and output
//it to XML via JAX-RS
}
EDIT 1
Wile my threads fetch data from somewhere and fill this information into a ConcurrentLinkedQueue I basically would like to perform some action in MyClass to update the XML output with the results. When all threads are terminated I would like to return true to the JAX-RS webservice which instantiated MyClass so the webservice knows all data has been fetched and it can now display the final XML file
EDIT 2
I am passing a Queue to threads so they can add items to the queue. When one driver is done adding items to the articleQueue I want to perform an action within my main class, polling the entity from the Queue and handing it over to the response object to display it in some way.
When I pass the queue to the threads, are they working with the same object or with a "copy" of the object so that changes within the thread do not effect the main object? That is not the behavior I want. When I check the size of the articleQueue within the Driver it is 18, the size of the articleQueue in the DriverController is 0.
Is there a nicer way to react when a thread has added something to the queue other than my while loop? How do I have to modify my code to acces the same object within different classes?
DriverController
public class DriverController {
Queue<Article> articleQueue;
ThreadPoolExecutor threadPool = null;
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(
maxPoolSize);
public DriverController(Response response) {
articleQueue = new ConcurrentLinkedQueue<Article>();
threadPool = new ThreadPoolExecutor();
Driver driver = new Driver(this.articleQueue);
threadPool.execute(driver);
// More drivers would be executed here which add to the queue
while (threadPool.getActiveCount() > 0) {
// this.articleQueue.size() gives back 0 here ... why?
if(articleQueue.size()>0){
response.addArticle(articleQueue.poll());
}
}
}
}
Driver
public class Driver implements Runnable{
private Queue<Article> articleQueue;
public DriverAlliedElectronics(Queue articleQueue) {
this.articleQueue = articleQueue;
}
public boolean getData() {
// Here would be the code where the article is created ...
this.articleQueue.offer(article);
return true;
}
public void run() {
this.getData();
// this.articleQueue.size() gives back 18 here ...
}
}
You should try to use following snippet
//Now I would like to wait until the threadPool is done working
threadPool.shutdown();
while (!threadPool.isTerminated()) {
try {
threadPool.awaitTermination(10, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Maybe a ExecutorCompletionService might be the right thing for you:
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html
Example from the link above:
void solve(Executor e, Collection<Callable<Result>> solvers)
throws InterruptedException, ExecutionException {
CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
for (Callable<Result> s : solvers)
ecs.submit(s);
int n = solvers.size();
for (int i = 0; i < n; ++i) {
Result r = ecs.take().get();
if (r != null)
use(r);
}
}
Instead of using execute you should use submit. This will return a Future instance on which you can wait for the task(s) to complete. That way you don't need polling or shutting down the pool.
I don't think there's a way to do this explicitly. You could poll the getCompletedTaskCount() to wait for that to become zero.
Why not collect the Future objects returned upon submission and check for all of those being completed ? Simply call get() on each one in turn. Since that call blocks you'll simply wait for each in turn and gradually fall through the set until you've waited on each on.
Alternatively you could submit the threads, and call shutdown() on the executor. That way, the submitted tasks will be executed, and then the terminated() method is called. If you override this then you'll get a callback once all tasks are completed (you couldn't use that executor again, obviously).
Judging from the reference documentation you have a few options:
ThreadPoolExecutor threadPool = null;
ThreadClass threadclass1;
ThreadClass threadclass2;
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(maxPoolSize);
puclic MyClass(){
threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue);
threadClass1 = new ThreadClass;
threadClass2 = new ThreadClass;
threadPool.execute(threadClass1);
threadPool.execute(threadClass2);
//Now I would like to wait until the threadPool is done working
//Option 1: shutdown() and awaitTermination()
threadPool.shutDown();
try {
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS)
}
catch (InterruptedException e) {
e.printStackTrace();
}
//Option 2: getActiveCount()
while (threadPool.getActiveCount() > 0) {
try {
Thread.sleep(1000);
}
catch (InterruptedException ignored) {}
}
//Option 3: getCompletedTaskCount()
while (threadPool.getCompletedTaskCount() < totalNumTasks) {
try {
Thread.sleep(1000);
}
catch (InterruptedException ignored) {}
}
}
All things considered, I think shutdown() and awaitTermination() is the best option of the three.
I think you're overengineering things a bit. You don't really care about the threads or the thread pool, and rightly so. Java provides nice abstractions so that you don't have to. You just need to know when your tasks are complete, and methods exist for that. Just submit your jobs, and wait for the futures to say they're done. If you really want to know as soon as a single task completes, you can watch all the futures and take action as soon as any one is finished. If not and you only care that everything is finished, you can remove some complexity from the code I'm about to post. Try this on for size (note MultithreadedJaxrsResource is executable):
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.*;
import java.util.concurrent.*;
#Path("foo")
public class MultithreadedJaxrsResource {
private ExecutorService executorService;
public MultithreadedJaxrsResource(ExecutorService executorService) {
this.executorService = executorService;
}
#GET
#Produces(MediaType.APPLICATION_XML)
public AllMyArticles getStuff() {
List<Future<Article>> futures = new ArrayList<Future<Article>>();
// Submit all the tasks to run
for (int i = 0; i < 10; i++) {
futures.add(executorService.submit(new Driver(i + 1)));
}
AllMyArticles articles = new AllMyArticles();
// Wait for all tasks to finish
// If you only care that everything is done and not about seeing
// when each one finishes, this outer do/while can go away, and
// you only need a single for loop to wait on each future.
boolean allDone;
do {
allDone = true;
Iterator<Future<Article>> futureIterator = futures.iterator();
while (futureIterator.hasNext()) {
Future<Article> future = futureIterator.next();
if (future.isDone()) {
try {
articles.articles.add(future.get());
futureIterator.remove();
} catch (InterruptedException e) {
// thread was interrupted. don't do that.
throw new IllegalStateException("broken", e);
} catch (ExecutionException e) {
// execution of the Callable failed with an
// exception. check it out.
throw new IllegalStateException("broken", e);
}
} else {
allDone = false;
}
}
} while (!allDone);
return articles;
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
AllMyArticles stuff =
new MultithreadedJaxrsResource(executorService).getStuff();
System.out.println(stuff.articles);
executorService.shutdown();
}
}
class Driver implements Callable<Article> {
private int i; // Just to differentiate the instances
public Driver(int i) {
this.i = i;
}
public Article call() {
// Simulate taking some time for each call
try {
Thread.sleep(1000 / i);
} catch (InterruptedException e) {
System.err.println("oops");
}
return new Article(i);
}
}
class AllMyArticles {
public final List<Article> articles = new ArrayList<Article>();
}
class Article {
public final int i;
public Article(int i) {
this.i = i;
}
#Override
public String toString() {
return "Article{" +
"i=" + i +
'}';
}
}
Done that way, you can plainly see that the tasks are returned in the order they complete, as the last task finishes first thanks to sleeping the shortest time. If you don't care about completion order and just want to wait for all to finish, the loop becomes much simpler:
for (Future<Article> future : futures) {
try {
articles.articles.add(future.get());
} catch (InterruptedException e) {
// thread was interrupted. don't do that.
throw new IllegalStateException("broken", e);
} catch (ExecutionException e) {
// execution of the Callable failed with an exception. check it out.
throw new IllegalStateException("broken", e);
}
}

Java: Threads, how to make them all do something

I am trying to implement nodes talking to each other in Java. I am doing this by creating a new thread for every node that wants to talk to the server.
When the given number of nodes, i.e. that many threads have been created, have connected to the server I want each thread to execute their next bit of code after adding to the "sharedCounter".
I think I need to use 'locks' on the shared variable, and something like signalAll() or notifyAll() to get all the threads going, but I can't seem to make clear sense of exactly how this works or to implement it.
Any help explaining these Java concepts would be greatly appreciated :D
Below is roughly the structure of my code:
import java.net.*;
import java.io.*;
public class Node {
public static void main(String[] args) {
...
// Chooses server or client launchers depend on parameters.
...
}
}
class sharedResource {
private int sharedCounter;
public sharedResource(int i) {
sharedCounter = i;
}
public synchronized void incSharedCounter() {
sharedCounter--;
if (sharedCounter == 0)
// Get all threads to do something
}
}
class Server {
...
for (int i = 0; i < numberOfThreads; i++) {
new serverThread(serverSocket.accept()).start();
}
...
sharedResource threadCount = new sharedResource(numberOfThreads);
...
}
class serverThread extends Thread {
...
//some code
Server.threadCount.incSharedCounter();
// Some more code to run when sharedCounte == 0
...
}
class Client {
...
}
     // Get all threads to do something
Threads (or rather Runnables, which you should implement rather than extending Thread) have a run method that contains the code they are expected to execute.
Once you call Thread#start (which in turn calls Runnable#run), the thread will start doing exactly that.
Since you seem to be new to multi-threading in Java, I recommend that you read an introduction to the Concurrency Utility package, that has been introduced in Java5 to make it easier to implement concurrent operations.
Specifically what you seem to be looking for is a way to "pause" the operation until a condition is met (in your case a counter having reached zero). For this, you should look at a CountDownLatch.
Indeed, the subject is broad, but I'll try to explain the basics. More details can be read from various blogs and articles. One of which is the Java trail.
It is best to see each thread as being runners (physical persons) that run alongside each other in a race. Each runner may perform any task while running. For example, take a cup of water from a table at a given moment in the race. Physically, they cannot both drink from the same cup at once, but in the virtual world, it is possible (this is where the line is drawn).
For example, take again two runners; each of them has to run back and forth a track, and push a button (shared by the runners) at each end for 1'000'000 times, the button is simply incrementing a counter by one each time. When they completed their run, what would be the value of the counter? In the physical world, it would be 2'000'000 because the runners cannot push the button at the same time, they would wait for the first one to leave first... that is unless they fight over it... Well, this is exactly what two threads would do. Consider this code :
public class ThreadTest extends Thread {
static public final int TOTAL_INC = 1000000;
static public int counter = 0;
#Override
public void run() {
for (int i=0; i<TOTAL_INC; i++) {
counter++;
}
System.out.println("Thread stopped incrementing counter " + TOTAL_INC + " times");
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new ThreadTest();
Thread t2 = new ThreadTest();
t1.start();
t2.start();
t1.join(); // wait for each thread to stop on their own...
t2.join(); //
System.out.println("Final counter is : " + counter + " which should be equal to " + TOTAL_INC * 2);
}
}
An output could be something like
Thread stopped incrementing counter 1000000 times
Thread stopped incrementing counter 1000000 times
Final counter is : 1143470 which should be equal to 2000000
Once in a while, the two thread would just increment the same value twice; this is called a race condition.
Synchronizing the run method will not work, and you'd have to use some locking mechanism to prevent this from happening. Consider the following changes in the run method :
static private Object lock = new Object();
#Override
public void run() {
for (int i=0; i<TOTAL_INC; i++) {
synchronized(lock) {
counter++;
}
}
System.out.println("Thread stopped incrementing counter " + TOTAL_INC + " times");
}
Now the expected output is
...
Final counter is : 2000000 which should be equal to 2000000
We have synchronized our counter with a shared object. This is like putting a queue line before only one runner can access the button at once.
NOTE : this locking mechanism is called a mutex. If a resource can be accessed by n threads at once, you might consider using a semaphore.
Multithreading is also associated with deadlocking. A deadlock is when two threads mutually waits for the other to free some synchronized resource to continue. For example :
Thread 1 starts
Thread 2 starts
Thread 1 acquire synchronized object1
Thread 2 acquire synchronized object2
Thread 2 needs to acquire object2 for continuing (locked by Thread 1)
Thread 1 needs to acquire object1 for continuing (locked by Thread 2)
Program hangs in deadlock
While there are many ways to prevent this from happening (it depends on what your threads are doing, and how they are implemented...) You should read about that particularly.
NOTE : the methods wait, notify and notifyAll can only be called when an object is synchronized. For example :
static public final int TOTAL_INC = 10;
static private int counter = 0;
static private Object lock = new Object();
static class Thread1 extends Thread {
#Override
public void run() {
synchronized (lock) {
for (int i=0; i<TOTAL_INC; i++) {
try {
lock.wait();
counter++;
lock.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
static class Thread2 extends Thread {
#Override
public void run() {
synchronized (lock) {
for (int i=0; i<TOTAL_INC; i++) {
try {
lock.notify();
counter--;
lock.wait();
} catch (InterruptedException e) {
/* ignored */
}
}
}
}
}
Notice that both threads are running their for...loop blocks within the synchronized block. (The result of counter == 0 when both threads end.) This can be achieved because they "let each other" access the synchronized resource via the resource's wait and notify methods. Without using those two methods, both threads would simply run sequentially and not concurrently (or more precisely, alternately).
I hope this shed some light about threads (in Java).
** UPDATE **
Here is a little proof of concept of everything discussed above, using the CountDownLatch class suggested by Thilo earlier :
static class Server {
static public final int NODE_COUNT = 5;
private List<RunnableNode> nodes;
private CountDownLatch startSignal;
private Object lock = new Object();
public Server() {
nodes = Collections.synchronizedList(new ArrayList<RunnableNode>());
startSignal = new CountDownLatch(Server.NODE_COUNT);
}
public Object getLock() {
return lock;
}
public synchronized void connect(RunnableNode node) {
if (startSignal.getCount() > 0) {
startSignal.countDown();
nodes.add(node);
System.out.println("Received connection from node " + node.getId() + " (" + startSignal.getCount() + " remaining...)");
} else {
System.out.println("Client overflow! Refusing connection from node " + node.getId());
throw new IllegalStateException("Too many nodes connected");
}
}
public void shutdown() {
for (RunnableNode node : nodes) {
node.shutdown();
}
}
public void awaitAllConnections() {
try {
startSignal.await();
synchronized (lock) {
lock.notifyAll(); // awake all nodes
}
} catch (InterruptedException e) {
/* ignore */
shutdown(); // properly close any connected node now
}
}
}
static class RunnableNode implements Runnable {
private Server server;
private int id;
private boolean working;
public RunnableNode(int id, Server server) {
this.id = id;
this.server = server;
this.working = true;
}
public int getId() {
return id;
}
public void run() {
try {
Thread.sleep((long) (Math.random() * 5) * 1000); // just wait randomly from 0 to 5 seconds....
synchronized (server.getLock()) {
server.connect(this);
server.getLock().wait();
}
if (!Thread.currentThread().isAlive()) {
throw new InterruptedException();
} else {
System.out.println("Node " + id + " started successfully!");
while (working) {
Thread.yield();
}
}
} catch (InterruptedException e1) {
System.out.print("Ooop! ...");
} catch (IllegalStateException e2) {
System.out.print("Awwww! Too late! ...");
}
System.out.println("Node " + id + " is shutting down");
}
public void shutdown() {
working = false; // shutdown node here...
}
}
static public void main(String...args) throws InterruptedException {
Server server = new Server();
for (int i=0; i<Server.NODE_COUNT + 4; i++) { // create 4 more nodes than needed...
new Thread(new RunnableNode(i, server)).start();
}
server.awaitAllConnections();
System.out.println("All connection received! Server started!");
Thread.sleep(6000);
server.shutdown();
}
This is a broad topic. You might try reading through the official guides for concurrency (i.e. threading, more or less) in Java. This isn't something with cut-and-dried solutions; you have to design something.

Categories