The Java executor classes are essentially a queue backed by a thread pool
of workers.

So suppose we create a new executor:

(def executor
  (java.util.concurrent.Executors/newFixedThreadPool 32))

This creates an ExecutorService object with a pool of 32 worker threads. We
can pass it a zero-argument function to execute:

(.execute executor (fn [] (prn "Hello World")))

This function is placed on a queue until one of the 32 worker threads is
available to process it. In this case the function prints a message, but
you could write something to send an email instead:

(defn queue-email [email]
  (.execute executor (fn [] (send-email email)))

If we execute "queue-email" 10,000 times, then 10,000 "send-email" jobs
will be passed to the executor. The executor will pass them onto its 32
workers, effectively processing 32 at a time until it exhausts the queue.

If you want fewer emails to be sent at once, you can reduce the worker
thread pool size. In my earlier example, I used an executor with only one
worker thread.

On Thu, 25 Oct 2018 at 18:17, <brj...@gmail.com> wrote:

> Hi James,
>
> Thanks! How would one create a thread that continuously monitors a mail
> queue and sends any mails in it? Or do you mean that I would create one
> thread per mail that I want to send? Wouldn't that create a problem if I'm
> about to send 10000 mails in one go?
>
> And thanks for the heads up regarding indefinite blocking - I'll make sure
> to guard against that.
>
> Thanks,
> Brjánn
>
> On Thu, 25 Oct 2018 at 18:57, James Reeves <ja...@booleanknot.com> wrote:
>
>> Hi Brjánn,
>>
>> Executing queued jobs in a background thread is a common task, and as it
>> happens there's a set of Java classes to do just that.
>>
>> (let [e (java.util.concurrent.Executors/newSingleThreadExecutor)]
>>   (.execute e #(prn "foo"))
>>   (.execute e #(prn "bar"))
>>   (Thread/sleep 1000)
>>   (.execute e #(prn "baz")))
>>
>> Don't worry about cleaning up a single thread. An inactive thread takes
>> up a minimal amount of VM memory and no CPU. You're going to use up more OS
>> resources deleting and recreating the thread.
>>
>> You do need to be careful that sending an email doesn't block
>> indefinitely, but usually I/O operations come with timeouts. Just ensure
>> you set a reasonable timeout and do something sensible when you can't send.
>>
>> On Thu, 25 Oct 2018 at 16:46, <brj...@gmail.com> wrote:
>>
>>> Hi,
>>>
>>> First, I would like to briefly present myself to the list. I'm a
>>> psychologist and researcher at the Karolinska Institutet in Stockholm,
>>> Sweden. I do research within the field of internet-based psychological
>>> treatment - which is a field that has grown a lot during the last 10-15
>>> years. I have developed my own web platform to deliver these treatments to
>>> patients with different mental and medical conditions. I wrote the first
>>> version in PHP, and not being a professional programmer, the code base is a
>>> big mess after > 10 years of development.
>>>
>>> Two years ago, a friend introduced me to Clojure. I had never worked
>>> with a lisp before, but I quickly fell completely in love with it. So many
>>> of the issues of programming in PHP completely disappeared! Words cannot
>>> express my gratitude to Rich for inventing Clojure, the core team, all
>>> developers out there who write extremely useful libraries, and my friend
>>> for introducing Clojure to me.
>>>
>>> I decided to completely rewrite my web platform in Clojure. I've chosen
>>> to do a gradual move from PHP to Clojure, meaning that I replace PHP code
>>> with Clojure code component by component and continuously test in
>>> production. Like I said, I'm not a professional programmer, and this
>>> venture poses a lot of challenges. I try to read everything I find in books
>>> and on the web, but when it comes to more complex issues, such as threads
>>> and async programming, I feel that I end up almost guessing and with a lot
>>> of trial and error. I have no idea how cautious one should be when
>>> launching a new thread (while it completely occupy the server???) and am
>>> often surprised when my go blocks suddenly freeze. I feel that I am at the
>>> mercy of the Clojure community if I want to understand these (and many
>>> other!) issues.
>>>
>>> This leads me to the subject of this email. I've decided to migrate my
>>> mail queue from PHP to Clojure. In PHP, it's just a cron job that executes
>>> every five minutes to send all emails (and actually also SMS-messages, but
>>> not really relevant) that have been queued.
>>>
>>> I've written a basic mock Clojure implementation with the following goals
>>> - All messages should be sent async, i..e, the web user should not have
>>> to wait while the email is being sent. -> I'm sending them in a separate
>>> thread.
>>> - I have a fear that if I have a thread dedicated only to sending
>>> emails, I'm wasting server resources. -> I want the thread to die 5 seconds
>>> after the last email in the queue has been sent.
>>>
>>> My implementation basically consists of
>>> - An eternal go loop that receives a notification through a channel if
>>> new messages have been queued
>>> - The go loop checks if the mail sender thread is running. If not, it
>>> starts it.
>>> - The mail sender thread dies 5 secs after the last email was sent
>>> - The state of the thread (running / not running) is stored in an agent
>>> to avoid race conditions (i.e., starting multiple threads or not starting a
>>> thread because it is running when its status is checked but stops right
>>> after).
>>>
>>> My code is here
>>> https://gist.github.com/brjann/2aef16849b9bd445374cb6b31efece60
>>>
>>> If any of you have had the time and energy to read this far (including
>>> the code), I would be very grateful for your input.
>>> - Is there a risk that my go block will hang?
>>> - Have I eliminated the risk for race conditions?
>>> - Do I really need to kill the thread or is there no risk for thread
>>> starvation on the server (I will probably
>>> - Could I use send instead of send-off? I guess that I am now using two
>>> threads, one for the sender and one each time I send a message using
>>> send-off.
>>> - Any newbie mistakes / coding style issues?
>>> - Could this be done in a better/simpler way???
>>>
>>> (Btw, I would be very grateful for feedback on the form of my question
>>> if you have any. Are there better/other forums? Could I present the
>>> question or code in a another manner to help you understand better?)
>>>
>>> I am happy for any replies - on the list or backchannel. And I hope that
>>> you feel that I have not misused your inbox (I may repeat this behavior...).
>>>
>>> Thanks,
>>> Brjánn
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clojure@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+unsubscr...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> ---
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to clojure+unsubscr...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>
>> --
>> James Reeves
>> booleanknot.com
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@googlegroups.com
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+unsubscr...@googlegroups.com
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to clojure+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>


-- 
James Reeves
booleanknot.com

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to