Jump to content

Multi-Threading Question

Ghost

Language: Java

 

I need a way to limit message count on my IRC bot to avoid a global ban from twitch for chat flooding.

 

There are two ways I considered doing this both involving a message queue.

  1. Each message starts a thread which takes a counting semaphore. This thread then blocks for 30 seconds and releases after that time. This would be a very clean solution as the queue would be entirely managed by the OS which means less work for me, however, it may result in creating hundreds of threads. These threads will be sleeping for most of their lifetime, but I'm not sure if it considered okay to launch hundreds of threads that do nothing, effectively. They won't take up time slices from the scheduler when they are asleep but they would consume a lot of memory and there would be a lot of overhead in creating them.
  2. Store a stack of timestamps and if a time-stamp is >30 seconds old remove it every time a message needs to be sent. Have a thread running that checks  the bottom of the stack every (10-50ms) to see if the time-stamp is >30 seconds old and remove if it is and then send a message from the highest position in the queue that has not been sent if it exists. When a message comes in to be sent it sends it immediately if there are <# messages in the queue.

1 has the downside of creating many threads that do nothing.

2 has the downside of needing 1 thread to poll the message list constantly.

 

2 could be improved to calculate the time needed to wait till the bottom message in the stack is 30 seconds old and send the message then, but I feel as if I am overcomplicating the problem at that stage.

 

Any thoughts on which would be the better approach?

Feel free to PM for any water-cooling questions. Check out my profile for more ways to contact me.

 

Add me to your circles on Google+ here or you can follow me on twitter @deadfire19.

Link to comment
Share on other sites

Link to post
Share on other sites

i don't know how twitch works and what is the rule that makes the banhammer strike, so i'll just assume that you can only send N messages in 30 seconds, correct me if i'm wrong

 

the way to go is surely the second one as the first, as you said, just spawns a ton of threads that are doing nothing

i would just hold a queue of messages to send, and a counter of "how many messages i sent in the last 30secs": when you send a message you increment the counter, and 30 seconds later you decrement it (maybe keeping a queue of timestamps)

the program keeps sending messages if they're available. if the counter reaches N, no message is sent and the program sleeps until the first "decrement timestamp" in the second queue fires

Link to comment
Share on other sites

Link to post
Share on other sites

Ghost If you wanted to do the second process there is perhaps a better way than checking every 10-30ms.  My thought reimplementing the second processes would be this (it is basically your concept, but lets the thread remain more inactive).

 

So you start with an empty queue, and your checking thread is permanently sleeping until it is woken up (look up synchronized or locks).  This way your thread basically is dormant at the beginning.

 

When a message arrives, add the timestamp into the queue and if and only if the queue was empty before wake up the dormant checking thread. (If the queue was not empty, the checking thread would be "running")

 

So nothing overly new yet, but now for the actual checking thread.

 

When the queue is empty the thread goes to sleep using synchronized or locks.

When there is an item in the queue this will not check every 10-30ms...instead use the following logic.

Check the first queue item as it will be the "oldest" message.  Now lets just say X = max time allowed in the buffer - (current time difference - message time)  so in your case the max time would be 30 second.  Now X will be the minimum amount of time the thread will have to wait around doing nothing, since it can't pop the message until 30 seconds.  So with that knowledge sleep the thread for X (actually if you want more accuracy you could sleep the thread a bit shorter X than say 100ms before and do your 10-30ms check stuff at this point).

 

So now you have a thread that calculates roughly how much time to sleep.

0b10111010 10101101 11110000 00001101

Link to comment
Share on other sites

Link to post
Share on other sites

-snip-

This was the implementation I went with in the end (before your reply, optimizing in some of the places you pointed out while writing the code):

 

http://pastebin.com/VUPJBiiZ

 

Feel free to critique.

 

A better way would be to pause the thread externally if there was no queue and reactivate it when needed, but one comparison every 250ms is so little compute that I don't think it would be worth it.

Feel free to PM for any water-cooling questions. Check out my profile for more ways to contact me.

 

Add me to your circles on Google+ here or you can follow me on twitter @deadfire19.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×