> For the complete documentation index, see [llms.txt](https://computer-networks-lab.gitbook.io/computer-networks-lab-manual/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://computer-networks-lab.gitbook.io/computer-networks-lab-manual/appendix/threading-interface.md).

# Threading Interface

At times, you might need several threads of execution to run in parallel. For instance, you might want to check if network messages have arrived while waiting for keyboard input. Threads allow you to have several lines of execution in parallel, which could solve this problem. This page will give you a brief overview of how to work with threading in python.

## Getting Started

Before you can use threads, you must import the `threading` module into your program. To do so, you can include the line below at the top of your python file, with the other includes.

```python
import threading
```

This will give you access to python's multithreading functionality. With that in hand, we can create an object of the `Thread` class using the `threading.Thread()` constructor. To create a thread, at the bare minimum, we need to tell it what function to run. Optionally we can also give it arguments.

The code below will create a thread, which will run the print function with the argument `"Hello World"`.

```python
import threading

t = threading.Thread(target = print, args = ("Hello World",))
```

You'll notice that we called `threading.Thread` and told it to call the `print` function with the argument `"Hello World"`.&#x20;

You might also notice the odd syntax of the `args` argument. The value of `args` ***must*** be a `tuple`. If you have at least two values in your tuple, you can list them as usual: `(val1, val2, val3)` for example. However, if you only have a single value in your tuple, you need to add a "*dummy*" comma at the end for it to be treated as a tuple: `(value, )`.

A final observation, if you've tried running this code, is that nothing happens. Nothing is printed. That is because, at this point, we have only ***created*** the thread. In order for the function to be executed, we must also `start` the thread. Let's extend our code to do so:

```python
import threading

t = threading.Thread(target = print, args = ("Hello World",))
t.start()
```

## Thread Lifetime

Once a thread is created and started, it will execute its target function until that function returns. Once the function returns, the thread exits.

You might want threads to exit when your main function ends. You can turn your thread into a `daemon` , which will exit once all of your non-`daemon` threads have exited. Your (default) main thread is not a `daemon` thread, so if you do not create any new non-`daemon` threads, then all of your `daemon` threads will exit when the main thread exits. To do so, we will add an argument to our constructor call:

```python
import threading

t = threading.Thread(target = <...>, args = <...>, daemon=True)
t.start()
```

You can also wait for a thread to exit, by using the `join()` function. This will block and wait until the target thread exits before continuing to the next instruction.

```python
# Version A
import threading

t = threading.Thread(target = input, args = ("Enter some text: ",))
t.start()

t.join()
print("The end")
```

Version A will wait until the input function has returned (so until the user has typed something on their keyboard) and only then print "The end".

```python
# Version B
import threading

t = threading.Thread(target = input, args = ("Enter some text: ",))
t.start()

print("The end")
```

Version B will start the thread, and immediately print "The end", without waiting for the user to type in input and for the `input` function to return.
