读书人

Ruby on Rails 入门之:(18) ruby线程

发布时间: 2012-10-13 11:38:17 作者: rapoo

Ruby on Rails 入门之:(18) ruby线程控制,线程同步

在Ruby中线程是用户级线程并依赖与操作系统。线程是进程中的一个实体,是被系统独立调度和分配的基本单位。线程可以与同属于同样个进程的其他线程共同共享进程的全部资源。但是线程不拥有资源,只需要一点在运行时必不可少的资源。


线程的基本控制,如果主进程结束,会结束所有的线程。所以如果你的线程在执行显示的任务,但是主进程却已经执行完毕,会看不到线程的任何输出。如链接中所示:

http://blog.csdn.net/weixingstudio/article/details/7796442


线程的创建可以使用Thread.new,同样可以以同样的语法使用Thread.start 或者Thread.fork这三个方法来创建线程。

创建线程并执行的基本代码:

[ruby] view plaincopy
  1. i=1
  2. puts "hello thread"
  3. puts Time.new
  4. #round=5
  5. #while i<round
  6. # puts "the #{i}th round"
  7. # i=i+1
  8. #end
  9. thread1=Thread.start 10 do |value|
  10. while i<value
  11. puts "#{i}"
  12. i=i+1
  13. end
  14. end
  15. thread1.join
  16. thread2=Thread.start do
  17. 10.times do |a|
  18. puts "the #{a+1} output"
  19. end
  20. end
  21. thread2.join

上面的代码中,线程thread1线程创建以后,调用了thread1.join方法,这个方法会挂起主线程,等待thread1线程完成,这样就可一在主线程结束之前看到线程thread1,thread2的输出消息。

上面的线程的运行结果:

[ruby] view plaincopy
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. the 1 output
  11. the 2 output
  12. the 3 output
  13. the 4 output
  14. the 5 output
  15. the 6 output
  16. the 7 output
  17. the 8 output
  18. the 9 output
  19. the 10 output

但是这样可以看到,线程的输出是等到线程thread1完全执行完毕以后才执行线程thread2,有经验的朋友就会知道线程的调度是随机的,所以如果没有thread1.join和thread2.join两个方法,线程的输出就会变得没有规律,下面我们该一下程序看看没有规律的线程输出。

[ruby] view plaincopy
  1. i=1
  2. puts "hello thread"
  3. puts Time.new
  4. #round=5
  5. #while i<round
  6. # puts "the #{i}th round"
  7. # i=i+1
  8. #end
  9. thread1=Thread.start 10 do |value|
  10. while i<value
  11. puts "#{i}\n"
  12. i=i+1
  13. end
  14. end
  15. thread2=Thread.start do
  16. 10.times do |a|
  17. puts "the #{a+1} output\n"
  18. end
  19. end
  20. thread1.join
  21. thread2.join

这样两个线程都开启以后,等调用join方法等待两个线程完成。

输出的结果:

[ruby] view plaincopy
  1. hello thread
  2. 2012-07-28 19:22:15 +0800
  3. 1
  4. the 1 output
  5. 2
  6. the 2 output
  7. 3
  8. the 3 output
  9. 4
  10. the 4 output
  11. 5
  12. 6
  13. the 5 output
  14. 7
  15. the 6 output
  16. 8
  17. the 7 output
  18. 9
  19. the 8 output
  20. the 9 output
  21. the 10 output

可以看到输出的结果已经变得没有规律了。


挂起当前的线程上面已经提到了,通过join方法可以等待指定的线程执行完毕。同时Ruby钟还有一种方法可以实现等待指定线程运行完毕,就是value方法,value方法还可以获得线程的值。通过Thread.current方法可以获得线程的id。如下面的代码:[ruby] view plaincopy
  1. #encoding:gbk
  2. require "thread"
  3. i=1
  4. puts "hello thread"
  5. puts Time.new
  6. #round=5
  7. #while i<round
  8. # puts "the #{i}th round"
  9. # i=i+1
  10. #end
  11. thread1=Thread.start 10 do |value|
  12. while i<value
  13. id=Thread.current
  14. puts "#{i} 当前执行的线程id:#{id}\n"
  15. i=i+1
  16. end
  17. end
  18. thread2=Thread.start do
  19. 10.times do |a|
  20. id=Thread.current
  21. puts "the #{a+1} output 当前执行的线程id:#{id}\n"
  22. end
  23. end
  24. thread1.join
  25. thread2.join

这里想让Ruby输出中文的话,需要添加语句到文件头:[ruby] view plaincopy
  1. #encoding:gbk
上面代码的执行结果:[html] view plaincopy
  1. hello thread
  2. 2012-07-28 19:29:35 +0800
  3. the 1 output 当前执行的线程id:#<Thread:0x87788e8>
  4. the 2 output 当前执行的线程id:#<Thread:0x87788e8>
  5. 1 当前执行的线程id:#<Thread:0x8778924>
  6. the 3 output 当前执行的线程id:#<Thread:0x87788e8>
  7. 2 当前执行的线程id:#<Thread:0x8778924>
  8. the 4 output 当前执行的线程id:#<Thread:0x87788e8>
  9. 3 当前执行的线程id:#<Thread:0x8778924>
  10. the 5 output 当前执行的线程id:#<Thread:0x87788e8>
  11. 4 当前执行的线程id:#<Thread:0x8778924>
  12. the 6 output 当前执行的线程id:#<Thread:0x87788e8>
  13. 5 当前执行的线程id:#<Thread:0x8778924>
  14. the 7 output 当前执行的线程id:#<Thread:0x87788e8>
  15. 6 当前执行的线程id:#<Thread:0x8778924>
  16. the 8 output 当前执行的线程id:#<Thread:0x87788e8>
  17. 7 当前执行的线程id:#<Thread:0x8778924>
  18. the 9 output 当前执行的线程id:#<Thread:0x87788e8>
  19. 8 当前执行的线程id:#<Thread:0x8778924>
  20. the 10 output 当前执行的线程id:#<Thread:0x87788e8>
  21. 9 当前执行的线程id:#<Thread:0x8778924>

线程的停止可以使用Thread.pass停止当前线程。还是那个程序,稍加改动:[ruby] view plaincopy
  1. i=1
  2. puts "hello thread"
  3. puts Time.new
  4. #round=5
  5. #while i<round
  6. # puts "the #{i}th round"
  7. # i=i+1
  8. #end
  9. thread1=Thread.start 10 do |value|
  10. while i<value
  11. puts "#{i} \n"
  12. i=i+1
  13. if i>5
  14. Thread.exit
  15. end
  16. end
  17. end
  18. thread2=Thread.start do
  19. 10.times do |a|
  20. puts "the #{a+1} output\n"
  21. end
  22. end
  23. thread1.join
  24. thread2.join

当thead1线程中i超过5以后,结束那个线程。输出结果:[html] view plaincopy
  1. hello thread
  2. 2012-07-28 19:39:42 +0800
  3. 1
  4. the 1 output
  5. 2
  6. the 2 output
  7. 3
  8. the 3 output
  9. 4
  10. the 4 output
  11. 5
  12. the 5 output
  13. the 6 output
  14. the 7 output
  15. the 8 output
  16. the 9 output
  17. the 10 output

同时线程的结束还可以使用Thread.exit。使用sleep函数让线程休眠,对于同样的程序进行修改:[ruby] view plaincopy
  1. i=1
  2. puts "hello thread"
  3. puts Time.new
  4. #round=5
  5. #while i<round
  6. # puts "the #{i}th round"
  7. # i=i+1
  8. #end
  9. thread1=Thread.start 10 do |value|
  10. sleep 3
  11. while i<value
  12. puts "#{i} \n"
  13. i=i+1
  14. end
  15. end
  16. thread2=Thread.start do
  17. 10.times do |a|
  18. puts "the #{a+1} output\n"
  19. end
  20. end
  21. thread1.join
  22. thread2.join

当线程thread1开启以后,休眠3秒钟,输出的结果:[html] view plaincopy
  1. hello thread
  2. 2012-07-28 19:43:37 +0800
  3. the 1 output
  4. the 2 output
  5. the 3 output
  6. the 4 output
  7. the 5 output
  8. the 6 output
  9. the 7 output
  10. the 8 output
  11. the 9 output
  12. the 10 output
  13. 1
  14. 2
  15. 3
  16. 4
  17. 5
  18. 6
  19. 7
  20. 8
  21. 9
可以看到线程thread2的所有输出都完成之后,线程thread1才从睡眠中唤醒,而且中间等待了大概有三秒钟的时间。

读书人网 >网络基础

热点推荐