Multiple threads is indeed one way to do this, but it has significant implications regarding how your whole program is written. Another way to do this -- and probably still the most common way on Linux -- is to use
asynchronous I/O. All operating systems have the notion of calling a function to initiate an I/O operation, and then later checking to see when it's done, or being notified when it's done. On UNIXy systems, it's called
select() or
pselect().
Here's a tutorial on how to use it.
Here is an introduction to doing the same sort of thing on Windows.