Two Approaches to Thread Creation in Python: Function-based vs Class-based Implementation

Nov 18, 2025 · Programming · 13 views · 7.8

Keywords: Python Multithreading | Thread Creation | threading Module

Abstract: This article provides a comprehensive exploration of two primary methods for creating threads in Python: function-based thread creation and class-based thread creation. Through comparative analysis of implementation principles, code structure, and application scenarios, it helps developers understand core concepts of multithreading programming. The article includes complete code examples and in-depth technical analysis, covering key topics such as thread startup, parameter passing, and thread synchronization, offering practical guidance for Python multithreading development.

Fundamentals of Python Multithreading Programming

In Python programming, multithreading serves as a crucial means for achieving concurrent execution. Threads are independent execution units within a process that share the same memory space, making inter-thread communication relatively simple and efficient. Python provides robust thread management capabilities through the threading module, allowing developers to choose different thread creation approaches based on specific requirements.

Function-based Thread Creation Approach

Function-based thread creation represents the most straightforward and commonly used method in Python. This approach eliminates the need to define new classes by directly using ordinary functions as thread execution targets. Its core advantages lie in code simplicity and ease of understanding, making it particularly suitable for simple concurrent tasks.

Below is a complete example of function-based thread creation:

from threading import Thread
from time import sleep

def threaded_function(arg):
    for i in range(arg):
        print("running")
        sleep(1)

if __name__ == "__main__":
    thread = Thread(target = threaded_function, args = (10, ))
    thread.start()
    thread.join()
    print("thread finished...exiting")

In this example, we first define an ordinary function threaded_function that accepts a parameter arg to control the number of iterations. Within the function, sleep(1) simulates time-consuming operations, ensuring we can observe the concurrent execution behavior of threads.

When creating the thread, we utilize the Thread class constructor, specifying the target function through the target parameter and passing required arguments via the args parameter. It's important to note that args must be a tuple, requiring comma notation even when passing a single argument.

The thread.start() method initiates the thread, causing it to begin executing the target function. Meanwhile, thread.join() ensures the main thread waits for the child thread to complete execution before proceeding, which proves crucial for scenarios requiring thread synchronization.

Class-based Thread Creation Approach

Beyond function-based methods, Python also supports creating custom thread classes by inheriting from the Thread class. This approach better suits complex thread logic, enabling encapsulation of more state and behavior within the class.

Here is example code for class-based thread creation:

import threading

class MyThread(threading.Thread):
    def __init__(self, thread_name, thread_ID):
        threading.Thread.__init__(self)
        self.thread_name = thread_name
        self.thread_ID = thread_ID
    
    def run(self):
        print(str(self.thread_name) + " " + str(self.thread_ID))

if __name__ == "__main__":
    thread1 = MyThread("GFG", 1000)
    thread2 = MyThread("GeeksforGeeks", 2000)
    thread1.start()
    thread2.start()
    print("Exit")

In this method, we create a subclass MyThread that inherits from threading.Thread. Within the constructor __init__, we first invoke the parent class constructor, then initialize custom attributes. Most importantly, we override the run method, which defines the actual task the thread will execute.

After creating thread instances, we initiate threads by calling the start() method, which automatically invokes our overridden run method. The class-based approach offers superior encapsulation, allowing maintenance of thread state and provision of additional methods within the class.

Comparative Analysis of Both Approaches

The function-based thread creation method offers these advantages: concise and intuitive code without requiring additional class definitions; suitability for simple task scenarios; straightforward parameter passing. Conversely, the class-based thread creation method better accommodates complex business logic, enabling encapsulation of more state and behavior while providing improved code organization.

In practical development, the choice between methods depends on specific requirements. For simple concurrent tasks, the function-based approach is recommended; for threads requiring maintenance of complex state or provision of rich interfaces, the class-based method proves more appropriate.

Thread Synchronization and Resource Management

Thread synchronization represents a critical topic in multithreading programming. When multiple threads need to access shared resources, thread safety considerations become essential. Python provides various synchronization mechanisms, including locks, semaphores, events, and more.

When using the join() method, attention must be paid to its blocking characteristics. The main thread calling a child thread's join() method will wait for that child thread to complete execution, which may cause performance issues in certain scenarios. Developers need to judiciously employ synchronization mechanisms based on actual requirements.

Practical Recommendations and Best Practices

In Python multithreading programming, we recommend adhering to these best practices: properly utilize thread pools for thread resource management; avoid modifying global variables within threads; employ thread-safe queues for inter-thread communication; remain mindful of Python's Global Interpreter Lock (GIL) impact on multithreading performance.

For I/O-intensive tasks, multithreading can significantly enhance program performance; however, for CPU-intensive tasks, due to GIL constraints, multithreading may not deliver expected performance improvements, making multiprocessing a more suitable consideration in such cases.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.