This question already has answers here:
wait until all threads finish their work in java
(17 answers)
Closed 6 years ago.
Say I'm using a HTTP requests library for downloading files. This library uses threads inside. Now, I want to wait on the main thread until other threads complete their execution.
All the other solutions that I found by googling only work if I have access to the Thread variables that were used in the library. But these are not accessible to me.
Here's what i'm using currently:
package smartzero.eightnoteight.testfirebase;
import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("email: ");
String email = in.nextLine();
System.out.print("password: ");
String password = in.nextLine();
Firebase fb = new Firebase("https://nullform.firebaseio.com");
fb.authWithPassword(email, password, new AuthResultHandler());
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static class AuthResultHandler implements Firebase.AuthResultHandler {
#Override
public void onAuthenticated(AuthData authData) {
System.out.println("authentication successful");
String uid = authData.getUid();
new RunTests(uid);
}
#Override
public void onAuthenticationError(FirebaseError firebaseError) {
System.out.println("authentication failed.");
}
}
}
PS: i'm testing firebase using firebase-client-jvm on my pc.
You should use the events provided by Firebase:
fb.authWithPassword(email, password, new AuthResultHandler(){
#Override
public void onAuthenticated(AuthData authData) {
//do something if authentication successful
}
#Override
public void onAuthenticationError(FirebaseError error) {
//handle error
}
});
You could, if you really want to wait in the main do this:
void main(String[] args) {
boolean finished = false;
fb.authWithPassword(email, password, new AuthResultHandler(){
#Override
public void onAuthenticated(AuthData authData) {
finished = true;
}
});
while (!finished){
Thread.sleep(1);
}
}
Thats more of a pseudocode. It doesnt catch the interrupted exception and blocks forever if there is an error (onAuthenticationError). Also i would not recommend this. Busy waiting is almost never a good idea.
On non-Android runtimes the Firebase Java client uses daemon threads, which will not prevent a process from exiting. You must handle this using a CountdownLatch or a Semaphore.
CountdownLatch
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
Your code on it:
package smartzero.eightnoteight.testfirebase;
import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) throws InterruptedException {
Scanner in = new Scanner(System.in);
System.out.print("email: ");
String email = in.nextLine();
System.out.print("password: ");
String password = in.nextLine();
in.close();
Firebase fb = new Firebase("https://nullform.firebaseio.com");
CountDownLatch done = new CountDownLatch(1);
fb.authWithPassword(email, password, new Firebase.AuthResultHandler(){
#Override
public void onAuthenticated(AuthData authData) {
System.out.println("authentication successful");
done.countDown();
}
#Override
public void onAuthenticationError(FirebaseError error) {
System.out.println("authentication failed.");
done.countDown();
}
});
done.await();
}
}
Semaphore
It is used to control the number of concurrent threads that are using a resource. You could think of it as tickets to use a resource. You set the number of tickets available when you create it, and when acquire() is called with no tickets left, your process will wait for one to become available (on a release() call). On your code it is being created with zero "tickets" available:
package smartzero.eightnoteight.testfirebase;
import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import java.util.Scanner;
import java.util.concurrent.Semaphore;
public class Main {
public static void main(String[] args) throws InterruptedException {
Scanner in = new Scanner(System.in);
System.out.print("email: ");
String email = in.nextLine();
System.out.print("password: ");
String password = in.nextLine();
in.close();
Firebase fb = new Firebase("https://nullform.firebaseio.com");
Semaphore semaphore = new Semaphore(0);
fb.authWithPassword(email, password, new Firebase.AuthResultHandler(){
#Override
public void onAuthenticated(AuthData authData) {
System.out.println("authentication successful");
semaphore.release();
}
#Override
public void onAuthenticationError(FirebaseError error) {
System.out.println("authentication failed.");
semaphore.release();
}
});
semaphore.acquire();
}
}
A CountdownLatch is really good for having one thread wait for one or more threads to complete one or more tasks before proceeding.
First, create the countdown latch with count of n, where n is the number events you want to wait on. Next, give the latch to the thread or threads doing the work. After that, the thread that should wait calls await() on the latch, and simultaneously the other threads begin working. When each of the worker threads is done, they call countdown() on the latch. When the latch counter hits zero, the waiting thread (or possibly threads) will unblock.
Related
So I'm receiving numerous messages from a stream - well, it's not a stream per se, it's really a method that's fired off when a message is received - and I would like to count the number of messages received in 10 seconds.
Here's what I have so far:
package com.example.demo;
import java.net.URI;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
public class ExampleClient extends WebSocketClient {
private float messagesRecievedCount;
public ExampleClient(URI serverUri) {
super(serverUri);
System.out.println("Created object");
setMessagesRecievedCount(0);
}
#Override
public void onOpen(ServerHandshake serverHandshake) {
System.out.println("Connection established!");
}
#Override
public void onMessage(String s) {
setMessagesRecievedCount(getMessagesRecievedCount() + 1);
}
public void getMessagesPerMinute(){
float start = getMessagesRecievedCount();
float end = 0;
long ten = System.currentTimeMillis() + 1000;
while(System.currentTimeMillis() < ten) {
end = getMessagesRecievedCount();
}
System.out.println("start: "+start+" end: "+end+
"Total messages: "+ (end-start)+"\n");
}
public float getMessagesRecievedCount() {
return messagesRecievedCount;
}
public void setMessagesRecievedCount(float messagesRecievedCount) {
this.messagesRecievedCount = messagesRecievedCount;
}
}
I have a global variable messagesRecievedCount which keeps a running count of messages received from a websocket stream. Whenever a message is received the onMessage() method is fired and it updates the message count. I want to count the number of messages received in 10 seconds (and extrapolate it to a minute) - for which I have the getMessagesPerMinute().
Obviously the way I'm doing it is not smart - it's blocking and the count of messages after 10 seconds is the same (when actually it isn't, I've actually received 20 messages). I feel like I should be doing threads but I don't know how to go about it. What would you suggest? I'm really new to this and just tinkering around.
This is the main class where I'm calling ExampleClient.java from:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.web.socket.WebSocketSession;
import java.net.URI;
import java.net.URISyntaxException;
#SpringBootApplication
public class DemoApplication {
private WebSocketSession clientSession;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
public DemoApplication () throws URISyntaxException {
ExampleClient c = new ExampleClient( new URI( "wss://example.com/" ) );
c.connect();
c.getMessagesPerMinute();
}
}
The c.connect() establishes the connection and the onMessage() is triggered soon after!
Your code actully runs fo 1 second (1000ms, I don't know if this is a typo or a voluntary simplification). One other problem is that it calls end = getMessagesRecievedCount(); repeatedly inside a while loop, while you actually need only the starting and final value. A way to solve this would be using Thread.sleep() (if you never need to cancel the counting midway):
public void getMessagesPerMinute(){
float start = getMessagesRecievedCount();
float end = 0;
try{
Thread.sleep(10000);
}
catch(InterruptedException e){
System.out.println("do something");
}
end = getMessagesRecievedCount();
System.out.println("start: "+start+" end: "+end+
"Total messages: "+ (end-start)+"\n");
}
For blocking the important thing is that this code runs in a different thread that the one updating the value of messagesRecievedCount or doing other things that you may want to do in the meanwhile, so calling it inside a new thread is probably the best solution. I'm not familiar with the framework you are using so it may be already using different threads that better suit this purpose.
If you intend to do something more with the variable messagesRecievedCount some synchronization would be required, but for an estimate of the number of messages for minute this should be good enough.
Here is some test code I used that you can hopefully adapt to better suit your case and play with to pinpoint the problem. The difference is quite constant in this case, but the values are clearly updated. Making the ExampleClient instance public is a shortcut which should probaby be avoided in the actual code.
public class Test{
public static ExampleClient example=new ExampleClient();
public static void main(String[] args){
Thread a=new MessagesPerTenSecondFetcher();
Thread b=new MessagesPerTenSecondFetcher();
Thread c=new MessagesPerTenSecondFetcher();
Thread d= new MessageProducer();
a.start();
d.start();
b.start();
try{
Thread.sleep(2000);
}
catch(InterruptedException e){
System.out.println("do something");
}
c.start();
}
}
class ExampleClient {
private float messagesRecievedCount;
public void onMessage(String s) {
setMessagesRecievedCount(getMessagesRecievedCount() + 1);
}
public void getMessagesPerMinute(){
float start = getMessagesRecievedCount();
float end = 0;
try{
Thread.sleep(10000);
}
catch(InterruptedException e){
System.out.println("do something");
}
end = getMessagesRecievedCount();
System.out.println("start: "+start+" end: "+end+
"Total messages: "+ (end-start)+"\n");
}
public float getMessagesRecievedCount() {
return messagesRecievedCount;
}
public void setMessagesRecievedCount(float messagesRecievedCount) {
this.messagesRecievedCount = messagesRecievedCount;
}
}
class MessagesPerTenSecondFetcher extends Thread{
#Override
public void run(){
Test.example.getMessagesPerMinute();
}
}
class MessageProducer extends Thread{
#Override
public void run(){
for(int i =0; i<100;i++){
Test.example.onMessage("a");
try{
Thread.sleep(130);
}
catch(InterruptedException e){
System.out.println("do something");
}
}
}
}
I have this program with two threads: lessonThread and questionThread. The lesson thread prints Lesson continues, while the question thread every 5 seconds asks Finish lesson? and asks a user for input via Scanner. I have a wait() call in questionThread that throws an exception. In the catch block I use System.exit() to terminate the program, however it doesn't work right away - only after many lesson messages. At the same time, if I go through breakpoints in both thread in a debugger, it System.exit() terminates the program very soon.
public class LessonNotify {
private volatile boolean finished;
private Scanner scanner = new Scanner(System.in);
private Thread lessonThread;
private Thread questionThread;
public static void main(String[] args) {
LessonNotify lesson = new LessonNotify();
lesson.lessonThread = lesson.new LessonThread();
lesson.questionThread = lesson.new QuestionThread();
lesson.lessonThread.start();
lesson.questionThread.start();
}
class LessonThread extends Thread {
#Override
public void run() {
while (!finished) {
System.out.println("Lesson continues");
}
}
}
class QuestionThread extends Thread {
private Instant sleepStart = Instant.now();
#Override
public void run() {
while (!finished) {
if (Instant.now().getEpochSecond() - sleepStart.getEpochSecond() >= 5) {
try {
lessonThread.wait();
} catch (Exception e) {
e.printStackTrace();
finished = true;
System.exit(0);
}
System.out.print("Finish a lesson? y/n");
String reply = scanner.nextLine().substring(0, 1);
switch (reply.toLowerCase()) {
case "y":
finished = true;
}
sleepStart = Instant.now();
lessonThread.notify();
}
}
}
}
}
That's just how exiting works. The messages printed by the other thread, especially because it has no breaks on the car, are already in various buffers. By using a debugger the thread is frozen or at least runs slower, thus, you don't observe it.
See my other answer. When I said 'this is not how you thread' - there are a billion reasons why, and this is one of the billion.
I am looking for a java concurrency solution to the following problem.
There are some tasks being run, and a section of code C.
C must wait for all tasks to complete. (With a timeout)
No tasks may commence until C has finished.
I have looked through the java.concurrency package and I found a few things of interest, but nothing seems to work quite right:
Phasers would allow one way blocking, but not two way.
Semaphores, ForkJoinTasks and others have counter-type features but none seem to do what I want.
I believe I could construct something using a phaser and a lock like so:
void C() {
synchronized(lock) {
phaser.awaitAdvanceInterruptibly(phase, 1, TimeUnit.SECONDS);
// Start work anyway if a task is taking too long.
doWork();
}
}
void someTask() {
synchronized(lock) {
phaser.register();
}
doTask().thenRun(
() -> phaser.arriveAndDeregister()
);
}
Now while I'm fairly sure this would work, I'm also aware its a bad idea to try to build your own concurrency solution. Is there a better way of doing this?
If there isn't, what would I use for the phase argument?
Edit: This problem is within a project involving a web client connection, and therefore the tasks arrive unpredictably. However, it is possible that this situation could be avoided by more careful design.
This being a specialized use case, I think we'll need to use multiple concurrency utilities for co-ordination. The below program should do it. Please feel free to post questions of any parts aren't clear -
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class TestClass {
private volatile int numOfActiveTasks = 0;
private Semaphore cSemaphore = new Semaphore(1);
private Semaphore taskSemaphore = new Semaphore(1);
private Object tasksLock = new Object();
//Test method
public static void main(String[] args) throws IOException {
TestClass testClass = new TestClass();
//Launch some task threads
ExecutorService taskES = Executors.newFixedThreadPool(2);
IntStream.range(1, 11).forEach((i) -> taskES.submit(() -> {
try {
testClass.executeTask();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
//Launch some C threads
ExecutorService cES = Executors.newFixedThreadPool(2);
IntStream.range(1, 5).forEach((i) -> cES.submit(() -> {
try {
testClass.C();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
taskES.shutdown();
cES.shutdown();
}
void C() throws InterruptedException {
try {
cSemaphore.acquire();
//If tasks are running, wait at-least n seconds
this.taskSemaphore.tryAcquire(1, TimeUnit.SECONDS);
print("C started running");
doCsWork();
} finally {
cSemaphore.release();
print("C stopped running");
}
}
void executeTask() throws InterruptedException {
//Do not start while C is running
cSemaphore.acquire();
cSemaphore.release();
synchronized (tasksLock) {
++numOfActiveTasks;
taskSemaphore.tryAcquire();
print("A task started running. Total " + numOfActiveTasks + " tasks running");
}
doTasksWork();
synchronized (tasksLock) {
--numOfActiveTasks;
if (numOfActiveTasks == 0) {
taskSemaphore.release();
}
print("A task stopped running. Total " + numOfActiveTasks + " tasks remaining");
}
}
void doCsWork() throws InterruptedException {
Thread.sleep(1000);
}
void doTasksWork() throws InterruptedException {
Thread.sleep(2000);
}
void print(String message) {
System.out.println(message);
}
}
I found a solution for this problem in java.util.concurrent.locks, which is perfect for my use case.
StampedLock lock;
void C() {
long stamp = lock.tryWriteLock(1, TimeUnit.SECONDS);
doWork();
lock.unlockWrite(stamp);
}
void someTask() {
long stamp = lock.readLock();
doTask().thenRun(() -> lock.unlockRead(stamp));
}
The key with the StampedLock class is that the readLock() is not exclusive, whereas the writeLock() is exclusive. It also supports timeouts, similar to the regular Lock.
Now I investigate semaphores. I googled following link about this theme:
link
Author of this link wrote about using semaphores for signaling. To show how it works he wrote custom semaphore.
custom semaphore code:
public class Semaphore {
private boolean signal = false;
public synchronized void take() {
this.signal = true;
this.notify();
}
public synchronized void release() throws InterruptedException{
while(!this.signal) wait();
this.signal = false;
}
}
about how use it in code he wrote following:
public class SendingThread {
Semaphore semaphore = null;
public SendingThread(Semaphore semaphore){
this.semaphore = semaphore;
}
public void run(){
while(true){
//do something, then signal
this.semaphore.take();
}
}
}
public class RecevingThread {
Semaphore semaphore = null;
public ReceivingThread(Semaphore semaphore){
this.semaphore = semaphore;
}
public void run(){
while(true){
this.semaphore.release();
//receive signal, then do something...
}
}
}
main:
Semaphore semaphore = new Semaphore();
SendingThread sender = new SendingThread(semaphore);
ReceivingThread receiver = new ReceivingThread(semaphore);
receiver.start();
sender.start();
As I understood order of execution should be following
send - receive
send - receive
send - receive
...
I tryed to write own code using this bluerprint
public class SendReceiveWithCustomSemaphore {
public static void main(String[] args) {
MySemaphore mySemaphore = new MySemaphore();
new Send(mySemaphore).start();
new Receive(mySemaphore).start();
}
}
class MySemaphore {
boolean flag = false;
public synchronized void take() throws InterruptedException {
flag = true;
notify();
}
public synchronized void release() throws InterruptedException {
while (!flag) {
wait();
}
flag = false;
}
}
class Send extends Thread {
MySemaphore mySemaphore;
public Send(MySemaphore semaphore) {
this.mySemaphore = semaphore;
}
#Override
public void run() {
int i = 0;
while (i++ < 10) {
System.out.println("send");
try {
mySemaphore.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Receive extends Thread {
MySemaphore mySemaphore;
public Receive(MySemaphore semaphore) {
this.mySemaphore = semaphore;
}
#Override
public void run() {
while (true) {
try {
mySemaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("receive");
}
}
}
output:
send
send
send
send
send
send
send
send
send
send
receive
Thus it is not expected behaviour for me.
I made a mistake then I wrote code or I didn't understand concept ?
What did author want to say?
Find a better tutorial.
The output that you see is about what I would expect. The "sender" thread never blocks, so it will go on printing "send", "send", "send" forever. Meanwhile, over in the "receiver" thread, each time it calls the semaphore.release() method, it will be blocked until the next time the sender gets to run.
I would expect to see lots of "send" messsages, with occasional "receive" messages mixed in---more or less what you describe seeing.
I don't know what that example is supposed to prove, but for me, it creates the impression that the author does not know how programmers expect Semaphores to behave.
Some authors provide examples of what not to do, or examples containing a deliberate mistake that will be "fixed" in a later example. Are you sure you are not following an example of that kind?
Edit: I followed the link, and it looks like the main problem is that the names were swapped in the definitions of the take() and release() methods. If you just switch the names, it makes more sense.
By the time ReceiveSemafore is started SendSemafore has already executed 10 times.
Consider using a CountDownLatch to start the two threads at the same time. Although as pointed out by Fuhrmanator this will not produce the alternating output that you are looking for.
For this i would use a bounded semaphore with one signal.
If you look at the code I have two ArrayLists that are called, pressed and released that are global. What I have to do is update those arrays with the keys that are to be pressed, then pass these updated arrays to my Thread, or update the thread.. this is the part where I'm a little lost on what I have to do.
The currently example(untested if runs), is a basic example of what I had in my actual program. When I ran it it would press the buttons once, then it would throw and error, I can't remember the error as I can't test it right now, but it had to do with the way I was using the thread.
QUESTION
How do I pass the arrays to my Thread, once the thread has been started.
Code Example:
import oscP5.OscEventListener;
import oscP5.OscMessage;
import oscP5.OscP5;
import oscP5.OscStatus;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Main implements OscEventListener {
protected BlockingQueue<Integer> _KeyQue = new ArrayBlockingQueue<>(1024);
Producer producer = new Producer(this._KeyQue);
Consumer consumer = new Consumer(this._KeyQue);
ThreadTest threadTest = new ThreadTest(this._KeyQue);
Thread prod;
Thread con;
Thread threadT;
OscP5 osc = new OscP5(this, 22556);
public static void main(String[] argv) {
Main main = new Main();
main.setup();
}
public void setup() {
prod = new Thread(producer);
con = new Thread(consumer);
threadT = new Thread(threadTest);
prod.start();
con.start();
threadT.start();
}
#Override
public void oscEvent(OscMessage theMessage) {
float val = Float.parseFloat(theMessage.arguments()[0].toString());
if (val == 1.0) {
producer.addKey(KeyEvent.VK_W);
producer.addKey(KeyEvent.VK_S);
} else {
consumer.removeKey(KeyEvent.VK_S);
}
threadTest.run();
}
#Override
public void oscStatus(OscStatus theStatus) {}
public class Producer implements Runnable {
protected BlockingQueue<Integer> _KeyQue = null;
public void addKey(int key) {
try {
this._KeyQue.put(key);
System.out.println("Key " + key +" added to queue");
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
public Producer(BlockingQueue<Integer> _KeyQue) {
this._KeyQue = _KeyQue;
}
public void run() {
}
}
public class Consumer implements Runnable {
protected BlockingQueue<Integer> _KeyQue = null;
public void removeKey(int key) {
try {
this._KeyQue.remove(key);
System.out.println("key " + key + " removed from queue");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public Consumer(BlockingQueue<Integer> _KeyQue) {
this._KeyQue = _KeyQue;
}
public void run() {
}
}
public class ThreadTest implements Runnable {
protected BlockingQueue<Integer> _KeyQue = null;
public ThreadTest(BlockingQueue<Integer> _KeyQue) {
this._KeyQue = _KeyQue;
}
public void run() {
try {
Robot robot = new Robot();
while(!this._KeyQue.isEmpty()) {
for (Integer x : this._KeyQue) {
System.out.println("Keys in que: " + x);
Thread.sleep(500);
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
Edit:
Ok, so I've taken a look at threads and BlockingQueue's, but the thing I still can't figure out is how to continue to run the ThreadTest's run() method without locking the program. In this example it doesn't run at all. When I directly call threadTest.run() it locks the program within it and doesn't allow for adding or removing elements.
So what I need to do is be able to run a thread in the background that is constantly running, looping through *_KeysQueue()* and, in this example, printout the number associated with the keys. This should all happen while allowing me to add and remove keys.
You can have a BlockingQueue and a method to add elements that would be called from every other thread. You can have a static method addKey that could be accessed from every other thread and that would look for adding the new key to the BlockingQueue.
You can use there the producer-consumer pattern and you can see the book Java Concurrency In Practice or the link that led me to the book, in the blog The Java Specialists. The book has examples of all queues, concurrent or synchronized lists, ways to implement code to do several things, and all without having to stop to read 50 pages about something. An example and a few paragraphs of every issue.
Have a setter method in your class
public class ThreadTest implements Runnable {
....
public void setPressedList(ArrayList<Integer> e) {
this.pressed = e;
}
public void setReleasedList(ArrayList<Integer> f)
{
this.released = f
}
}
ArrayList are not thread-safe so you should not used them this way : it could work or it could fail.
Moreover you should use some kind of synchronization mechanism instead of busy-waiting which consume resources for nothing.
So have a look at the BlockingQueue collection which will give you a simple data-passing mechanism between your threads.