#Is while(true) a bad usage?
1 messages · Page 1 of 1 (latest)
Detected code, here are some useful tools:
<@&987246399047479336> please have a look, thanks.
it kinda is
whats wrong with a simple if?
why do you even need a loop
to check is something is in a list?
for example, imagine we have a message broker and we want to use it to ping another server,
sending the message ping and giving an id in the message
the other server return pong, how to get it?
at the method called when we got a message, add the response in a list (pong and his id)
after having sended the message, launche a while(true) to wait in the list the pong
but u already have a list
and a list has the contains method
so to figure out whether a list contains a given thing, u dont need any loops
u simply call the method and thats it
persons.contains(john)
but the list will only contain our value after receiving the pong
so you have two threads?
yes
well then you kinda need a similar structure
what struct you mean?
like usually you have a queue instead of a list
and then
while (true) {
var item = queue.take();
}
and a BlockingQueue so it blocks
fifo
there's not necessarily an order in my case, as I may have to collect other, heavier information, so some may arrive before others.
yeah u should have a global task queue that contains all incoming messages
and then a busy-loop as shown on that
the stuff squid is talking about is exactly the classes made for these kind of things
so u should use it
its easier, faster, better, ...
it waits until it receives a new item and then u can process it
Okay, for my case I have a global concurent hashmap and some thread (si some while(true)) need to get " her response" but theys don't care about other response, I just ignore it?
what are you storing in that map
i'm asking concretely
I use it for some case
because 90% of the time a queue is the right thing to use for communicating between threads
and if you just say "no, i'm using map" I can't intelligently give advice
because i don't understand why a map is involved
lets say I should to store instance
ig thats not really helpful
public int sendPingMessageToServer2(Message m) {
(ping message contain an id)
calling message borker method to send message
Borker.sendMessage(m);
while(true) {
if(!ourmap.contain(id)) {
continue
}
System.out.println(ourmap.get(id).getPongLatence)
}
}
here we listen message received
public void onMessage(Message m) {
if(m.getType == MessageType.pong) {
ourmap.put(m)
}
}
that's more or less what I'm trying to do
okay
and If I don't want to block the thread with my while true, I just have to do my while(true) in antother thread?
it will work?
the while (true) kinda must be on a different thread anyways
maybe I should use a completable future
not sure what you mean
usually you basically have a different thread that has a while (true) with a blocking queue.take() call using a BlockingQueue
I'm still not quite sure how to proceed, so I'll get back to you in a while to tell you what I think I've found.
likely not
Here I add a completable future to execute the while in async and not blocking the thread, it can work like this?
public int sendPingMessageToServer2(Message m) {
(ping message contain an id)
calling message borker method to send message
Borker.sendMessage(m);
CompletableFuture f instancied;
f.thenaccept(()->{
while(true) {
if(!ourmap.contain(id)) {
continue
}
return ourMap.get(id);
}
})
Message pong = f.complete();
System.out.println(pong.getPongLatence)
}
here we listen message received
public void onMessage(Message m) {
if(m.getType == MessageType.pong) {
ourmap.put(m)
}
}
Detected code, here are some useful tools:
with queue, when I .peek() I got the head, how can I get other objects?
I just loop it?
do you know what a queue is?
no, you most certainly do not need a CompletableFuture
While True will boock the thread no?
thats why you run it in a different thread
More or less
one second. I will make you an example
Ah yes I don't need you have reason
import java.time.Duration;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
record Message(int id, String payload) {}
void main() throws Exception {
var q = new LinkedBlockingQueue<>();
var stopBackgroundThread = new AtomicBoolean(false);
var backgroundThread = Thread.startVirtualThread(() -> {
while (!stopBackgroundThread.get()) {
try {
var msg = q.take();
System.out.println("Got message: " + msg);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
q.put(new Message(1, "Hello"));
Thread.sleep(Duration.ofMillis(500));
q.put(new Message(2, "World"));
Thread.sleep(Duration.ofMillis(500));
q.put(new Message(3, "!!!"));
stopBackgroundThread.set(true);
backgroundThread.join();
System.out.println("DONE");
}
But my code with completable future is correct ?
no
What is the problem ?
A browser interface to the Java compiler to experiment with the language
well aside from you sending totally broken psuedocode
a CompletableFuture is not the correct mechanism for running a background thread
that is either a thread directly or an executor service
its basically in the name of CompletableFuture
Yes I know My question about just the code itself not his implémentation
I précise that there are a lot of while(true) who acces to the list, in the code I think .take delete it, it will generate problems no?
Every while should acces to every messages to get the correct
Sorry man, your english is a bit broken
Are you implying that you have a single producer, but multiple consumer threads?
Yes really I am.sorry
Yes, imagine I want to make a lot of ping
so you want to handle all of those pings in parallel?
Yes we can say that
import java.time.Duration;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
record Ping() {}
void main() throws Exception {
var q = new LinkedBlockingQueue<>();
var stopBackgroundThread = new AtomicBoolean(false);
var backgroundThread = Thread.startVirtualThread(() -> {
while (!stopBackgroundThread.get()) {
try {
var msg = q.take();
Thread.startVirtualThread(() -> {
try {
Thread.sleep(Duration.ofMillis(300));
System.out.println(msg);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
q.put(new Ping());
q.put(new Ping());
q.put(new Ping());
Thread.sleep(Duration.ofMillis(500));
q.put(new Ping());
q.put(new Ping());
q.put(new Ping());
Thread.sleep(Duration.ofMillis(500));
q.put(new Ping());
stopBackgroundThread.set(true);
backgroundThread.join();
System.out.println("DONE");
}
then you have one consumer read from the queue
and that consumer kicks off its own subtasks
For this case Is not more simply to just while a .get(id) on concurenthashmap like I said (we dont have to loop all messages, de know what message we want)) I am not a pro but it seem most simpl?
again, concurrent hash map is not the correct mechanism
it is not meant to be used as a queue
declaration: module: java.base, package: java.util.concurrent, class: ConcurrentHashMap
if you want to, read the documentation for it
your biggest problem is that you have no way to be "done" with a message
your loop that looks like this
while (true) {
if (m.get(k)) {
}
}
won't exit unless you break
which implies a thread per key
which is an extremely strange situation
i am not sure about the concurrency properties of .get - presumably it will work but unlike a q.take() which will probably yield your thread back to the scheduler
m.get(k) will make it a hot loop
If I have 10 threads and the time it takes for one thread to retrieve its message from the head, the other 9 will be put on hold until the head is free, is this not a problem?
Okay okay Its good
Thanks for your help