4

我有点担心这个。
想象一下最简单的版本控制方式,程序员只需从主存储库中复制所有目录,如果主存储库仍然相同,则在更改文件后反向执行。如果它已被另一个人更改,他们必须再试一次。

当程序员的数量增加时,重试次数自然也会增加,但它可能与程序员的数量不成正比。
如果十个程序员工作,每人一个工作需要一个小时,那么完成所有工作至少需要十个小时。
如果他们是认真的,大约 9 + 8 + 7 + ... 1 = 45个工时将一事无成。
数百名程序员中,大约 99 + 98 + ... 1 = 4950个工时付诸东流。

我试图计算重试次数并得到结果。

资源

(defn fib [n] 
   (if  (or (zero? n) (= n 1)) 
       1 
      (+  (fib (dec n) )  (fib (- n 2))))) 

(defn calc! [r counter-A counter-B counter-C n]
  (dosync
   (swap! counter-A inc)
   ;;(Thread/sleep n)
   (fib n)
   (swap! counter-B inc)
   (alter r inc)
   (swap! counter-C inc)))

(defn main [thread-num n]
  (let [r (ref 0)
        counter-A (atom 0)
        counter-B (atom 0)
        counter-C (atom 0)]
    (doall (pmap deref
              (for [_ (take thread-num (repeat nil))]
                (future (calc! r counter-A counter-B counter-C n)))))
    (println thread-num " Thread. @ref:" @r)
    (println "A:" @counter-A ", B:" @counter-B ", C:" @counter-C)))

CPU:2.93GHz 四核 Intel Core i7
结果

user> (time (main 10 25))
10  Thread. @ref: 10
A: 53 , B: 53 , C: 10
"Elapsed time: 94.412 msecs"
nil
user> (time (main 100 25))
100  Thread. @ref: 100
A: 545 , B: 545 , C: 100
"Elapsed time: 966.141 msecs"
nil
user> (time (main 1000 25))
1000  Thread. @ref: 1000
A: 5507 , B: 5507 , C: 1000
"Elapsed time: 9555.165 msecs"
nil

我将工作更改为 (Thread/sleep n) 而不是 (fib n) 并得到了类似的结果。

user> (time (main 10 20))
10  Thread. @ref: 10
A: 55 , B: 55 , C: 10
"Elapsed time: 220.616 msecs"
nil
user> (time (main 100 20))
100  Thread. @ref: 100
A: 689 , B: 689 , C: 117
"Elapsed time: 2013.729 msecs"
nil
user> (time (main 1000 20))
1000  Thread. @ref: 1000
A: 6911 , B: 6911 , C: 1127
"Elapsed time: 20243.214 msecs"
nil

在线程/睡眠的情况下,我认为重试次数可能会超过这个结果,因为 CPU 可用。
为什么重试次数不增加?

谢谢。

4

2 回答 2

5

因为您实际上并没有产生 10、100 或 1000 个线程!创建一个future 并不总是创建一个新线程。它在后台使用线程池,在其中不断排队作业(或者Runnable是技术性的)。线程池是一个缓存线程池,它重用线程来运行作业。

因此,在您的情况下,您实际上并没有产生 1000 个线程。如果您想查看重试操作,请获得以下级别future- 创建您自己的线程池并将Runnables 推入其中。

于 2010-09-19T19:15:46.667 回答
1

自我回答

我修改了 main 函数不使用 pmap 并得到了计算结果。

(defn main [thread-num n]
  (let [r (ref 0)
        counter-A (atom 0)
        counter-B (atom 0)
        counter-C (atom 0)]
    (doall (map deref (doall (for [_ (take thread-num (repeat nil))]
                   (future (calc! r counter-A counter-B counter-C n))))))
    (println thread-num " Thread. @ref:" @r)
    (println "A:" @counter-A ", B:" @counter-B ", C:" @counter-C)))

纤维

user=> (main 10 25)
10  Thread. @ref: 10
A: 55 , B: 55 , C: 10
nil
user=> (main 100 25)
100  Thread. @ref: 100
A: 1213 , B: 1213 , C: 100
nil
user=> (main 1000 25)
1000  Thread. @ref: 1000
A: 19992 , B: 19992 , C: 1001
nil

线程/睡眠

user=> (main 10 20)
10  Thread. @ref: 10
A: 55 , B: 55 , C: 10
nil
user=> (main 100 20)
100  Thread. @ref: 100
A: 4979 , B: 4979 , C: 102
nil
user=> (main 1000 20)
1000  Thread. @ref: 1000
A: 491223 , B: 491223 , C: 1008
nil
于 2010-09-20T19:46:56.137 回答