Terminating a Thread

Table of contents:

Problem

You want to kill a thread before the end of the program.

Solution

A thread terminates if it reaches the end of its code block. The best way to terminate a thread early is to convince it to reach the end of its code block. This way, the thread can run cleanup code before dying.

This thread runs a loop while the instance variable continue is true. Set this variable to false, and the thread will die a natural death:

	require 	hread

	class CounterThread < Thread
	 def initialize
	 @count = 0
	 @continue = true

	 super do
	 @count += 1 while @continue
	 puts "I counted up to #{@count} before I was cruelly stopped."
	 end
	 end

	 def stop
	 @continue = false
	 end
	end

	counter = CounterThread.new
	sleep 2
	counter.stop
	# I counted up to 3413544 before I was cruelly stopped.

If you need to stop a thread that doesn offer a stop-like function, or you need to stop an out-of-control thread immediately, you can always call Thread#terminate. This method stops a thread in its tracks:

	t = Thread.new { loop { puts I am the unstoppable thread! } }
	# I am the unstoppable thread!
	# I am the unstoppable thread!
	# I am the unstoppable thread!
	# I am the unstoppable thread!
	t.terminate

Discussion

Its better to convince someone they should do something than to force them to do it. The same is true of threads. Calling Thread.terminate is a bit like throwing an exception: it interrupts the normal flow of execution in an unpredictable place. Worse, theres no equivalent of a begin/ensure construct for thread termination, so calling THRead.terminate may corrupt your data or leave your program in an inconsistent state. If you plan to stop a thread before the program is over, you should build that capability into the thread object itself.

A common type of thread implements a loop: threads that process requests from a queue, or that periodically poll for new data. In these, the end of an iteration forms a natural stopping point. These threads can benefit from some simple VCR-style controls: pause, unpause, and stop.

Heres a Thread subclass which implements a loop that can be paused or stopped in a predictable way. A code block passed into the Thread constructor would implement the entire loop, but the code block passed into the LoopingThread constructor should implement only one iteration of the loop. Setup and cleanup code should be handled in the methods before_loop and after_loop.

	class LoopingThread < Thread
	 def initialize
	 @stopped = false
	 @paused = false
	 super do
	 before_loop
	 until @stopped
	 yield
	 Thread.stop if @paused
	 end
	 after_loop
	 end
	 end

	 def before_loop; end
	 def after_loop; end

	 def stop
	 @stopped = true
	 end

	 def paused=(paused)
	 @paused = paused
	 run if !paused
	 end
	end

Heres the CounterThread class from the Solution, implemented as a LoopingThread. Ive added a reader method for count so we can peek at its value when the thread is paused:

	class PausableCounter < LoopingThread
	 attr_reader :count

	 def before_loop
	 @count = 0
	 end

	 def initialize
	 super { @count += 1 }
	 end

	 def after_loop
	 puts "I counted up to #{@count} before I was cruelly stopped."
	 end
	end

	counter = PausableCounter.new
	sleep 2
	counter.paused = true
	counter.count # => 819438
	sleep 2
	counter.count # => 819438
	counter.paused = false
	sleep 2
	counter.stop
	# I counted up to 1644324 before I was cruelly stopped.
	counter.count # => 1644324



Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net