Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
289 views
in Technique[技术] by (71.8m points)

multithreading - Clojure Running Multiple Threads with Functions with zero or one input

I'm experimenting in Clojure with running independent threads and I'm getting different behaviors I don't understand.

For my code editor I'm using Atom (not emacs), REPL is Chlorine.

I'm testing a really simple function that just prints numbers. This one prints from 100 to 1 and takes no inputs:

(defn pl100 []
  "pl100 = Print Loop from 100 to 1"
  (loop [counter 100]
    (when (pos? counter)
      (do
        (Thread/sleep 100)
        (println (str "counter: " counter))
        (recur (dec counter))))))

This one does the exact same thing, except it takes an input:

(defn pl-n [n]
    "pl-n = Print Loop from n to 1"
    (loop [counter n]
      (when (pos? counter)
        (do
          (Thread/sleep 100)
          (println (str "counter: " counter))
          (recur (dec counter))))))

When I use

(.start (Thread. #(.run pl100)))
; --> prints to console REPL
; --> runs with no errors

this code

  1. prints to the console REPL (where I call lein) and
  2. runs with no errors

When I use

(.start (Thread. #(.run (pl-n 100))))
; prints to console REPL
; --> java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "target" is null

this code

  1. prints to the console REPL
  2. ends with the above exception

When I use

(.start (Thread. pl100))
; --> prints to the console REPL
; --> runs with no errors  

this code

  1. prints to the console REPL
  2. runs with no errors

When I use

(.start (Thread. (pl-n 100)))
; --> prints to Atom REPL, not console REPL!
; ends with exception 
; Execution error (NullPointerException) at java.lang.Thread/<init> (Thread.java:396).
; name cannot be null
; class java.lang.NullPointerException

this code

  1. prints to the Atom REPL (I'm using Atom, not emacs)! Not to the console REPL like the others
  2. ends with exception

So, can someone please help me understand:

  1. Why is it when I'm running a function that takes an input, Java gives an error? Why are the function calls not equivalent?
  2. What is (.run ...) doing?
  3. Why is it that sometimes the code prints to the console and other times to Atom/Chlorine?
question from:https://stackoverflow.com/questions/65852747/clojure-running-multiple-threads-with-functions-with-zero-or-one-input

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

To answer in brief: Thread.run requires a function. Your first exhibit gives it a function, pl100, and works as you expect:

#(.run pl100)

Something altogether different would happen if you gave .run not a function, but instead the value returned by calling the pl100 function. In fact, pl100 returns nil, so Thread.run would throw a NullPointerException:

#(.run (pl100)) ;; NullPointerException

That explains why your second exhibit did not do what you expected. pl-n returned nil, and then you got an exception when you passed nil to Thread.run:

#(.run (pl-n 100)) ;; NullPointerException

To bridge the gap - between Thread.run which requires a function of no arguments, and your function pl-n which requires an argument, you could introduce a function-of-no-arguments (to satisfy Thread.run) which calls pl-n with the desired argument. Idiomatically this would be an anonymous function. Unfortunately, you can't nest #() within #(), so you will have to use the more verbose (fn [] ...) syntax for one of the anonymous functions, most likely the outer one.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...