Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create threads only if same thread name does'nt exist as active thread (Python)

How to only create threads assigned with name, such that same name threads are not active? For eg.:

threading.Thread(name='t1', target=foo).start() 
threading.Thread(name='t1', target=foo).start()

Here, since already thread named t1 is running, the second t1 should be cancelled. It is to avoid redundant threads performing the same task. But, once the first t1 dies, and another thread with same names i.e. 't1' arrives, then it should run.
The constraints are: 10+ threads may try to generate. Thread Name are generated using random.randint(1,10). So, I need to check during runtime only with the thread name.

Here is my code:

import logging
import time
import threading
import random

logging.basicConfig(level=logging.DEBUG, format='[%(levelname)s] (%(threadName)-10s) %(message)s', )

e = threading.Event()
Thread_list = ['default']

def worker():
    logging.info('Starting')
    time.sleep(3)
    logging.info('Ending')
    try:
        Thread_list.remove(threading.currentThread().getName())
    except:
        pass
    return

def application_manager(appId):
    #print threading.enumerate()
    event_is_set = e.wait(2)
    if event_is_set:
        th = threading.Thread(name=appId, target=worker)
        Thread_list.append(threading.currentThread().getName())
        th.start()
    else:
        logging.warning('Task already running.')

def subsystem_request():
    for i in range(10):
        appId = random.randint(1,10)
        application_manager(appId)

def fdir():
    logging.debug('FDIR')
    count = 0
    cur = threading.currentThread()
    time.sleep(2)
    for fd in range(5):
        e.clear()
        for t in threading.enumerate():
            for u in threading.enumerate():
                if t.getName() == cur:
                    e.set()
                elif (t.getName() in u.getName()) and (t.getName() != 'MainThread'):
                    e.clear()
                else:
                    e.set()


fdir_thread = threading.Thread(name='fdir_thread', target=fdir)
fdir_thread.setDaemon(True)
fdir_thread.start()
subsystem_request()

fdir_thread.join()

Actual output:

[DEBUG] (fdir_thread) FDIR
[WARNING] (MainThread) Task already running.
[WARNING] (MainThread) Task already running.
[WARNING] (MainThread) Task already running.
[WARNING] (MainThread) Task already running.
[WARNING] (MainThread) Task already running.
[WARNING] (MainThread) Task already running.
[WARNING] (MainThread) Task already running.
[WARNING] (MainThread) Task already running.
[WARNING] (MainThread) Task already running.
[WARNING] (MainThread) Task already running.

Another actual output:

[INFO] (9         ) Starting
[INFO] (7         ) Starting
[INFO] (1         ) Starting
[INFO] (9         ) Starting     //This thread should be cancelled  
[INFO] (4         ) Starting
[INFO] (10        ) Starting
[INFO] (2         ) Starting
[INFO] (7         ) Starting     //This thread should be cancelled  
[INFO] (5         ) Starting
[INFO] (8         ) Starting
[INFO] (9         ) Ending
[INFO] (1         ) Ending
[INFO] (7         ) Ending
[INFO] (9         ) Ending
[INFO] (2         ) Ending
[INFO] (10        ) Ending
[INFO] (4         ) Ending
[INFO] (7         ) Ending
[INFO] (5         ) Ending
[INFO] (8         ) Ending 

Expected output:

[INFO] (9         ) Starting
[INFO] (7         ) Starting
[INFO] (1         ) Starting
[INFO] (4         ) Starting
[INFO] (10        ) Starting
[INFO] (2         ) Starting
[INFO] (5         ) Starting
[INFO] (8         ) Starting
[INFO] (9         ) Ending
[INFO] (1         ) Ending
[INFO] (7         ) Ending
[INFO] (2         ) Ending
[INFO] (10        ) Ending
[INFO] (4         ) Ending
[INFO] (5         ) Ending
[INFO] (8         ) Ending

Each of these active threads have unique name during.
I am using threading.Event(). So, function application_manager waits for 2 secs and func fdir() checks using threading.enumerate() for same name, if yes, then e.clear() else, e.set(). Once, e.set(), application_manager() will create the thread.

I want to use fdir() to check and then communicate to application_manager() for thread generation or cancellation.
NOTE: fdir() and application_manager() should be 2 different threads.

like image 686
timekeeper Avatar asked Mar 15 '26 02:03

timekeeper


2 Answers

A better approach would be to refactor your code to use a Lock object

t1 = threading.Lock()

def foo(*args):
    if not t1.acquire(wait=False):
         return

    # do stuff

While this does exactly what you describe - i.e. if somehting else holds the lock the execution will be "cancelled" you are probably better off refactoring to avoid calling the thread altogether.

like image 143
scytale Avatar answered Mar 16 '26 16:03

scytale


You can use the thread.is_alive() function.

    if t1.is_alive() == 0:
        threading.Thread(name='t1', target=foo).start()

https://docs.python.org/2/library/threading.html

EDIT:

Using:

    texists = 0
    for t in threads:
        if t.name() == 't1':
            texists = 1

You can check if it exists then use an if statement to make it if it doesn't.

like image 34
Nick stands with Ukraine Avatar answered Mar 16 '26 15:03

Nick stands with Ukraine



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!