关于Python的线程程序设计
fuqiang_huang
|
1#
fuqiang_huang 发表于 2008-01-09 16:45
关于Python的线程程序设计
一、为什么用线程(Thread)?
在现阶段应用程序设计技术中,线程扮演很重要的角色,比如好多中间件是基于线程的、JAVA GUI应用等。 大面积应用采用线程的理由如下: 1、并行计算 2、并行I/O处理 3、异步I/O事件处理 二、什么是线程(Thread)? 1、先说一下什么是进程(Process)? 通过学习操作系统的基本原理你可以了解到它的重要性和有用性,主要是提升CPU的处理效率,主要内容有:什么是进程,进程的状态,进程的调度,进程的结构与标识, 进程的空间,进程的上下文切换,进程的处理方法,进程与程序的区别等。 2、线程是类似进程的,只有大小、粒度的不同 线程有时也叫轻量级(lightweight)进程,占有比线程更小的空间,切换的代价小,实际情况下依赖于具体的线程系统,它们都有自己的中断方法,关 于中断的技术要引起关注,因为线程的粒度小,有时要引起极大的关注,都可以创建自己的子线程或子进程,在UNIX/LINUX中用fork()创建子线 程,子共亨父的方法也是类同的。 三、Python的线程模块 有两个thread.py和threading.py,前者是早期的,相对来说简单一些。 用例子说明如下,注意研究lock是如何形成的 server.py # this is the server import socket # networking module import sys import thread # note the globals v and nclnt, and their supporting locks, which are # also global; the standard method of communication between threads is # via globals # function for thread to serve a particular client, c def serveclient(c): global v,nclnt,vlock,nclntlock while 1: # receive letter from c, if it is still connected k = c.recv(1) if k == ' ': break # concatenate v with k in an atomic manner, i.e. with protection # by locks vlock.acquire() v += k vlock.release() # send new v back to client c.send(v) c.close() nclntlock.acquire() nclnt -= 1 nclntlock.release() # set up Internet TCP socket lstn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) port = int(sys.argv[1]) # server port number # bind lstn socket to this port lstn.bind(('127.0.0.1', 4000)) # start listening for contacts from clients (at most 2 at a time) lstn.listen(5) # initialize concatenated string, v v = ' ' # set up a lock to guard v vlock = thread.allocate_lock() # nclnt will be the number of clients still connected nclnt = 2 # set up a lock to guard nclnt nclntlock = thread.allocate_lock() # accept calls from the clients for i in range(nclnt): # wait for call, then get a new socket to use for this client, # and get the client's address/port tuple (though not used) (clnt,ap) = lstn.accept() # start thread for this client, with serveclient() as the thread's # function, with parameter clnt; note that parameter set must be # a tuple; in this case, the tuple is of length 1, so a comma is # needed thread.start_new_thread(serveclient(clnt)) # shut down the server socket, since it's not needed anymore lstn.close() # wait for both threads to finish while nclnt > 0: pass print 'the final value of v is', v client1.py # simple illustration of thread module # two clients connect to server; each client repeatedly sends a letter, # stored in the variable k, which the server appends to a global string # v, and reports v to the client; k = ' 'means the client is dropping out; when all clients are gone, server prints the final string v # this is the client; usage is # python clnt.py server_address port_number import socket # networking module import sys # create Internet TCP socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host = sys.argv[1] # server address port = int(sys.argv[2]) # server port # connect to server s.connect((host,port )) while(1): # get letter k = raw_input('enter a letter:') s.send(k) # send k to server # if stop signal, then leave loop if k == ' ': break v= s.recv(1024) # receive v from server (up to 1024 bytes) print v s.close() # close socket 下面是threading的,联系java想一下相关方面 srvr如何? # simple illustration of threading module # multiple clients connect to server; each client repeatedly sends a # value k, which the server adds to a global string v and echos back # to the client; k = ’’ means the client is dropping out; when all # clients are gone, server prints final value of v # this is the server import socket # networking module import sys import threading # class for threads, subclassed from threading.Thread class class srvr(threading.Thread): # v and vlock are now class variables v = ’’ vlock = threading.Lock() id = 0 # I want to give an ID number to each thread, starting at 0 def __init__(self,clntsock): # invoke constructor of parent class threading.Thread.__init__(self) # add instance variables self.myid = srvr.id srvr.id += 1 self.myclntsock = clntsock # this function is what the thread actually runs; the required name # is run(); threading.Thread.start() calls threading.Thread.run(), # which is always overridden, as we are doing here def run(self): while 1: # receive letter from client, if it is still connected k = self.myclntsock.recv(1) if k == ’’: break # update v in an atomic manner srvr.vlock.acquire() srvr.v += k srvr.vlock.release() # send new v back to client self.myclntsock.send(srvr.v) self.myclntsock.close() # set up Internet TCP socket lstn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) port = int(sys.argv[1]) # server port number # bind lstn socket to this port lstn.bind((’’, port)) # start listening for contacts from clients (at most 2 at a time) lstn.listen(5) nclnt = int(sys.argv[2]) # number of clients mythreads = [] # list of all the threads # accept calls from the clients for i in range(nclnt): # wait for call, then get a new socket to use for this client, # and get the client’s address/port tuple (though not used) (clnt,ap) = lstn.accept() # make a new instance of the class srvr s = srvr(clnt) # keep a list all threads mythreads.append(s) # threading.Thread.start calls threading.Thread.run(), which we # overrode in our definition of the class srvr s.start() # shut down the server socket, since it’s not needed anymore lstn.close() # wait for all threads to finish for s in mythreads: s.join() print ’the final value of v is’, srvr.v |