How would I have a thread wait on a lambda?

This is my first time messing with threads. The project takes user input with a lambda, so I need to wait until that lambda gets valid data to resume the thread. From my research I havent found a good way to do that other than while (var == null) {} which doesn't seem ideal.
29 Replies
JavaBot
JavaBot2mo ago
This post has been reserved for your question.
Hey @blockgoblin31! Please use /close or the Close Post button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically marked as dormant after 300 minutes of inactivity.
TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.
nikcho-kouhai
nikcho-kouhai2mo ago
what input are you taking?
blockgoblin31
blockgoblin31OP2mo ago
Right now just a string from terminal, but thats for testing.
nikcho-kouhai
nikcho-kouhai2mo ago
well what do you mean by valid data?
blockgoblin31
blockgoblin31OP2mo ago
oh it needs to be one of three strings(selecting an option) specifically im looking for one of "draft", "set", or "random"
nikcho-kouhai
nikcho-kouhai2mo ago
why don't you just check if the input is equal to one of those things ?
blockgoblin31
blockgoblin31OP2mo ago
because I can't stop the main thread until the user gives input(This is eventally going to be server side code on something with multiple users)
nikcho-kouhai
nikcho-kouhai2mo ago
so let me see if I got this right you have a main thread which shouldn't stop running so you have delegated the user input to another thread and you are now wondering how to notify the main thread when valid input has been provided?
blockgoblin31
blockgoblin31OP2mo ago
no, user input is handled on the main thread. I'm passing the thing that handles user input a lambda to run the message through and I want to continue the side thread when that lambda has gotten valid input
nikcho-kouhai
nikcho-kouhai2mo ago
you just said you can't stop the main thread until the user gives input
blockgoblin31
blockgoblin31OP2mo ago
I'm not
nikcho-kouhai
nikcho-kouhai2mo ago
can the main thread block or can it not block?
blockgoblin31
blockgoblin31OP2mo ago
the main thread is getting a lambda that extends a specific interface for it to run messages through as a simplified example:
SelectionType type;
//runner handles the user input
runner.captureMessagesFrom(user, (message) -> {
switch (message.toLowerCase()) {
case "draft" -> type = SelectionType.DRAFT;
case "set" -> type = SelectionType.SET;
case "random" -> type = SelectionType.RANDOM;
default -> return false;
}
return true;
}
//use type for something
SelectionType type;
//runner handles the user input
runner.captureMessagesFrom(user, (message) -> {
switch (message.toLowerCase()) {
case "draft" -> type = SelectionType.DRAFT;
case "set" -> type = SelectionType.SET;
case "random" -> type = SelectionType.RANDOM;
default -> return false;
}
return true;
}
//use type for something
nikcho-kouhai
nikcho-kouhai2mo ago
who runs this function? is it the main thread or some other thread
blockgoblin31
blockgoblin31OP2mo ago
its run on the main thread when it gets a message and it gets the message from side threads that are actually doing the listening for user input
nikcho-kouhai
nikcho-kouhai2mo ago
right so what is the problem with validating the input before sending the message off to the main thread?
blockgoblin31
blockgoblin31OP2mo ago
the problem is I need to know that type is not null before the code continues, and that requires the specific user to send a valid message. the main thread can't just wait forever because then we wouldnt handle messages from other users so I need the code to wait until the value is set, and I'm not sure how to do that
nikcho-kouhai
nikcho-kouhai2mo ago
this is confusing
blockgoblin31
blockgoblin31OP2mo ago
(well other than while (type == null) {})
nikcho-kouhai
nikcho-kouhai2mo ago
in the first place you can't set type from inside the lambda
blockgoblin31
blockgoblin31OP2mo ago
yeah I know, that was just quicker for my example
nikcho-kouhai
nikcho-kouhai2mo ago
how does the main thread handle this message? Is it running an event loop? like run me through what happens when some thread receives some data from somewhere why can't it validate that data before sending it off to the main thread
blockgoblin31
blockgoblin31OP2mo ago
So let me phrase this differently(I don’t know exactly how the main code works, I’m writing an addon with an api), all messages go through the main thread and this is triggered by a message. So for other messages to be processed the main thread has to be freed, and this needs another message before it can finish its task.
nikcho-kouhai
nikcho-kouhai2mo ago
so im assuming the main thread is ran by this api then? again, what is the problem with validating the input in the current thread before captureMessageFrom wait a second do you want the side thread to wait for type to be set in this example? in other words:
SelectionType type;
//runner handles the user input
runner.captureMessagesFrom(user, (message) -> {
switch (message.toLowerCase()) {
case "draft" -> type = SelectionType.DRAFT;
case "set" -> type = SelectionType.SET;
case "random" -> type = SelectionType.RANDOM;
default -> return false;
}
return true;
}
//wait until type !=null
//use type for something
SelectionType type;
//runner handles the user input
runner.captureMessagesFrom(user, (message) -> {
switch (message.toLowerCase()) {
case "draft" -> type = SelectionType.DRAFT;
case "set" -> type = SelectionType.SET;
case "random" -> type = SelectionType.RANDOM;
default -> return false;
}
return true;
}
//wait until type !=null
//use type for something
is this what you are trying to do?
blockgoblin31
blockgoblin31OP2mo ago
Yes That lambda is where we get the input (it’s the message parameter), and it’s run on the main thread later
nikcho-kouhai
nikcho-kouhai2mo ago
okay you can do this multiple ways the simplest is with a CountDownLatch
SelectionType type;
final CountDownLatch latch = new CountDownLatch(1);

runner.captureMessagesFrom(user, (message) -> {
try{
switch (message.toLowerCase()) {
case "draft" -> type = SelectionType.DRAFT;
case "set" -> type = SelectionType.SET;
case "random" -> type = SelectionType.RANDOM;
default -> return false;
}
return true;
}finally {
latch.countDown();
}

});
try {
latch.await();
} catch (InterruptedException e) {
//handle interrupt as you see fit
}

//use type for something
SelectionType type;
final CountDownLatch latch = new CountDownLatch(1);

runner.captureMessagesFrom(user, (message) -> {
try{
switch (message.toLowerCase()) {
case "draft" -> type = SelectionType.DRAFT;
case "set" -> type = SelectionType.SET;
case "random" -> type = SelectionType.RANDOM;
default -> return false;
}
return true;
}finally {
latch.countDown();
}

});
try {
latch.await();
} catch (InterruptedException e) {
//handle interrupt as you see fit
}

//use type for something
the thread will block on await() until another calls countDown() you can find out more about the CountDownLatch here: https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html I suggest before jumping into multi-threaded code to have a look at synchronization blocks, locks and atomic variables it's also important to keep in mind that depending on your code the thread on await() might block indefinitely if the main thread shuts down before processing the message just learn a bit more about this before doing multi-threaded stuff
blockgoblin31
blockgoblin31OP2mo ago
Thank you, this worked!
JavaBot
JavaBot2mo ago
If you are finished with your post, please close it. If you are not, please ignore this message. Note that you will not be able to send further messages here after this post have been closed but you will be able to create new posts.
JavaBot
JavaBot2mo ago
Post Closed
This post has been closed by <@501514065068294154>.

Did you find this page helpful?