队列管理器的创建:
tf.train.QueueRunner(queue,enqueue_ops = None):
参数解释:
queue:一个队列
enqueue_ops
create_threads(sess,coord=None,start = False);创建线程来运行给定会话的入队操作,返回一个线程的实例
参数的解释:
start:布尔值,如果是True就启动线程,如果是False的话,调用者要是想启动线程就必须调用start()
coord:线程协调器,后面的线程管理器需要用到
#模拟异步操作:子线程存入数据,主线程从子线程的队列中读取数据
#1.定义一个队列:大小是1000
Q = tf.FIFOQueue(1000,tf.float32)
#2.定义子线程需要怎么处理数据,这里我们把数据每次都+1
var = tf.Variable(0.0) #初始值是0.0
data = tf.assign_add(var,1.0) #每次都把var这个变量的值+1,为什么不直接var+1呢,因为这是两个不同的op,
en_q = Q.enqueue(data) #进队列
#3.定义一个队列的任务管理器,可以指定多个子线程,接下来我们指定两个
qr = tf.train.QueueRunner(Q,enqueue_ops=[en_q]*2)
#不要忘记之前定义过的变量要初始化
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
#初始化变量
sess.run(init_op)
#正式开启子线程;这一步必须在会话中完成,在这里设置参数start=True就表示在此时已经开启子线程
threads = qr.create_threads(sess,start=True)
#主线程不断地读取数据
for i in range(300):
print(sess.run(Q.dequeue()))
如果你这时候去运行他会报错:
CancelledError: Enqueue operation was cancelled
这是因为主线程运行300次后就关闭了,这时候会话也关闭了,但是子线程需要运行1000次后才会关闭,所以这时候在会话关闭的情况下去运行子线程,(会话是进行资源管理的)子线程就得不到运行的资源了,这时候程序就会报错,提示会话已经关闭了,你被强制停止了
那该怎么办呢?
这里我们会用到一个叫线程协调器的函数:
tf.train.Coordinator():实现一个简单的机制来协调一组线程的终止
参数可以有如下:
request_stop() ===>请求线程停止:这是针对子线程运行的内容很重要的情况下调用的参数
should_stop() ===>强制停止
join(threadName) ===>回收线程
#模拟异步操作:子线程存入数据,主线程从子线程的队列中读取数据
#1.定义一个队列:大小是1000
Q = tf.FIFOQueue(1000,dtypes=tf.float32)
#2.定义子线程需要怎么处理数据,这里我们把数据每次都+1
var = tf.Variable(0.0) #初始值是0.0
data = tf.assign_add(var,1.0) #每次都把var这个变量的值+1,为什么不直接var+1呢,因为这是两个不同的op,
en_q = Q.enqueue(data) #进队列
#3.定义一个队列的任务管理器,可以指定多个子线程,接下来我们指定两个
qr = tf.train.QueueRunner(Q,enqueue_ops=[en_q]*2)
#不要忘记之前定义过的变量要初始化
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
#初始化变量
sess.run(init_op)
#开启线程管理器
coord = tf.train.Coordinator()
#正式开启子线程;这一步必须在会话中完成,在这里设置参数start=True就表示在此时已经开启子线程,指定了一个线程管理器coord
threads = qr.create_threads(sess,coord=coord,start=True)
#主线程不断地读取数据
for i in range(300):
print(sess.run(Q.dequeue()))
#开始回收子线程
coord.request_stop()
coord.join(threads) #回收的线程是threads