worker threads to finish their tasks in the absence of join calls or sleepsbut it can prevent programs like the one in example - from shutting down when they wish to make this example work with threadinguse the following alternative code (see queuetest py in the examples tree for complete version of thisas well as thread-countthreading pyalso in the treefor case where this refusal to exit can come in handy)import threadingqueuetime def producer(idnumdataqueue)def consumer(idnumdataqueue)if __name__ ='__main__'for in range(numconsumers)thread threading thread(target=consumerargs=(idataqueue)thread daemon true else cannot exitthread start(waitfor [for in range(numproducers)thread threading thread(target=producerargs=(idataqueue)waitfor append(threadthread start(for thread in waitforthread join(print('main thread exit 'or time sleep(long enough here we'll revisit the daemons and exits issue in while studying guisas we'll seeit' no different in that contextexcept that the main thread is usually the gui itself running the script nowas coded in example - the following is the output of this example when run on my windows machine notice that even though the queue automatically coordinates the communication of data between the threadsthis script still must use lock to manually synchronize access to the standard output streamqueues synchronize data passingbut some programs may still need to use locks for other purposes as in prior examplesif the safeprint lock is not usedthe printed lines from one consumer may be intermixed with those of another it is not impossible that consumer may be paused in the middle of print operationc:\pp \system\threadsqueuetest py consumer got =[producer id= count= consumer got =[producer id= count= consumer got =[producer id= count= consumer got =[producer id= count= consumer got =[producer id= count= consumer got =[producer id= count= consumer got =[producer id= count= consumer got =[producer id= count= consumer got =[producer id= count= threads