python java主线程结束,子线程还能运行么启动了一个子线程,为什么子线程是java主线程结束,子线程还能运行么运行完以后才运行的?

import java.util.concurrent.CountDownLatch;
/**
* @filename
: MyThread.java
* @description
: 描述(中文)
* @author
: lvyuanjun
* @create
: 2016年2月24日 下午2:04:30
*
* Modification History:修改日志
* Date
Author
Version
description
* -------------------------------------------------------------------------------
* 2016年2月24日 下午2:04:30
lvyuanjun
*/
public class MyThread {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(3); //子线程计算器
System.out.println("start...");
FirstThread f = new FirstThread(countDownLatch);
Thread thread = new Thread(f);
thread.start();
SecondThread s = new SecondThread(countDownLatch);
Thread thread1 = new Thread(s);
thread1.start();
ThreeThread t = new ThreeThread(countDownLatch);
Thread thread2 = new Thread(t);
thread2.start();
countDownLatch.await(); //等待子线程计算器为零时,则所有的子线程都已经运行完成
System.out.println("end...");
}
}
class FirstThread implements Runnable {
private CountDownLatch countDownLatch;
public FirstThread(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
}
public void run() {
System.out.println("FirstThread start....");
try {
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
System.out.println("FirstThread start1....");
countDownLatch.countDown(); //子线程执行完之后,子线程计算器减一,直至到零
}
}
}
class SecondThread implements Runnable{
private CountDownLatch countDownLatch;;
public SecondThread(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println("SecondThread start....");
try {
Thread.sleep(1000*9);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
System.out.println("SecondThread start1....");
countDownLatch.countDown();<span style="font-family: Arial, Helvetica, sans-serif;">//子线程执行完之后,子线程计算器减一,直至到零</span>
}
}
}
class ThreeThread implements Runnable{
private CountDownLatch countDownLatch;;
public ThreeThread(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println("ThreeThread start....");
try {
Thread.sleep(1000*3);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
System.out.println("ThreeThread start1....");
countDownLatch.countDown(); <span style="font-family: Arial, Helvetica, sans-serif;">//子线程执行完之后,子线程计算器减一,直至到零</span>
}
}
}
函数的执行过程从上往下执行,参考先执行函数名,不执行函数内部,只有函数被调用时才执行。def f1():
print("f1")
print("main函数")
def f2():
print('f2')
f2()
print("main函数2")
f1()
上面这段话会依次输出:main函数f2main函数2f1类的执行是从上往下,先只执行函数名(其他部分顺序执行)当实例化类对象时,会执行_init_,所以类的执行顺序是先执行__new__,再执行__init__,再执行普通方法,最后执行__del__class People:
print('出生')
def run(self):
print('跑')
def __init__(self):
print('1')
def eat(self):
print('eat')
print('生孩子')
baby=People()
baby.run()
上面这段话会依次输出:出生(注意,会先输出出生!!!)生孩子1跑有关多线程主要是学习了threading.Thread()的使用方法#创建Thread类的实例对象thread=Thread(target=threadFun,args=(‘参数1’,‘参数2’))#执行start方法就会创建新线程thread.start()#在主线程中执行join(),会等待thread对应的线程结束之后再执行后面的代码thread.join()#主线程只是一个比喻,执行.py文件,python编辑器就会创建一个线程
print('主线程执行代码')
from threading import Thread
from time import sleep
#定义一个函数,作为新线程执行的入口函数
def threadFun(arg1,arg2):
print('子线程 开始')
print(f'线程函数参数是{arg1},{arg2}')
sleep(5)
print('子线程 结束')
#创建Thread类的实例对象
thread=Thread(target=threadFun,args=('参数1','参数2'))
#执行start方法就会创建新线程
thread.start()
#在主线程中执行join(),会等待thread对应的线程结束之后再执行后面的代码
thread.join()
print('主线程结束')
还有Lock函数会给数据加锁,让多线程先后访问数据#操作共享数据前,申请获取锁bankLock.acquire()#操作完共享数据后,申请释放锁bankLock.release()from threading import Thread,Lock
from time import sleep
bank={
'TeacherBu':0
}
bankLock=Lock()
def depoist(theadidx,amount):
#操作共享数据前,申请获取锁
bankLock.acquire()
balance=bank['TeacherBu']
sleep(0.1)#模拟操作所消耗的时间
bank['TeacherBu']=balance+amount
print(f'子线程{theadidx}存钱结束!')
#操作完共享数据后,申请释放锁
bankLock.release()
threadList=[]
for index in range(10):
#实例化一个线程对象 index
thread=Thread(target=depoist,args=(index,10))
thread.start()
threadList.append(thread)
for thread in threadList:
thread.join()
print(f'主线程结束,最后账户余额为{bank["TeacherBu"]}')
Python中实现多线程需要使用到 threading 库,其中每一个 Thread类 的实例控制一个线程。Thread类#类签名def __init__(self, group=None, target=None, name=None,args=(), kwargs=None, *, daemon=None):简单介绍一些初始化参数:target: 指定线程由 run () 方法调用的可调用对象。默认为 None, 意味着不调用任何内容。name: 指定该线程的名称。 在默认情况下,创建一个唯一的名称。args: target调用的实参,元组格式。默认为 (),即不传参。daemon: 为False表示父线程在运行结束时需要等待子线程结束才能结束程序,为True则表示父线程在运行结束时,子线程无论是否还有任务未完成都会跟随父进程退出,结束程序。线程启动:import threadingdef worker(arg):#线程执行的目标函数print("I'm working {}".format(arg))print("Fineshed")t = threading.Thread(target=worker,args=(threading.current_thread(),),name="firstworker")#线程对象t.start()#启动线程运行结果:I'm working <_MainThread(MainThread, started 10936)>Fineshed上面例子中,当函数执行完之后,线程也就跟着退出了。线程的传参:import threadingdef add(x,y):print(x+y)t = threading.Thread(target=add,args=(4,5))t.start()print("====end===")运行结果:9====end===线程的传参和函数传参没有区别,只需要注意传入的必须为元祖格式。线程退出:如果线程中任务是无限循环语句,那这个线程将无法自动停止。Python线程退出条件有以下几种:1、线程内的函数语句执行完毕,线程自动结束2、线程内的函数抛出未处理的异常import threadingimport timedef worker(arg):while True:time.sleep(1)print("I'm working {}".format(arg))print("Fineshed")t = threading.Thread(target=worker,args=(threading.current_thread(),),name="firstworker")t.start()运行结果:I'm working <_MainThread(MainThread, stopped 2468)>I'm working <_MainThread(MainThread, stopped 2468)>I'm working <_MainThread(MainThread, stopped 2468)>...上面例子中,线程启动后,将一直循环下去,线程不会自动退出。import threadingimport timedef worker(arg):count = 0while True:if count > 5:raise RuntimeError(count)time.sleep(1)print("I'm working {}".format(arg))count += 1print("Fineshed")t = threading.Thread(target=worker,args=(threading.enumerate(),))t.start()print("====end===")运行结果:====end===I'm working [<_MainThread(MainThread, stopped 10992)>]I'm working [<_MainThread(MainThread, stopped 10992)>]I'm working [<_MainThread(MainThread, stopped 10992)>]I'm working [<_MainThread(MainThread, stopped 10992)>]I'm working [<_MainThread(MainThread, stopped 10992)>]I'm working [<_MainThread(MainThread, stopped 10992)>]Exception in thread Thread-1:Traceback (most recent call last):File "C:/python/test.py", line 8, in workerraise RuntimeError(count)RuntimeError: 6上面例子中,演示了触发异常自动退出线程。但最先打印的是主程序的"===end==="语句,是因为在程序中,主线程启动一个线程后,不会等待子线程执行完毕,就继续执行了后续语句,在执行完主线程语句后,发现还有子线程没有结束,于是等待子线程执行结束,子线程在运行时抛出了未处理的异常,最终子线程结束,主线程也随之结束。这里需要了解daemon线程和non-daemon线程,稍后就会介绍。threading属性:threading.current_thread() 返回当前线程对象threading.main_thread() 返回主线程对象threading.active_count() 返回处于Active状态的线程个数threading.enumerate() 返回所有存活的线程的列表,不包括已经终止的线程和未启动的线程threading.get_ident() 返回当前线程的ID,非0整数举例:import threadingimport timedef showthreadinfo():print("current thread = {}".format(threading.current_thread()))print("main thread = {}".format(threading.main_thread()))print("active thread count = {}".format(threading.active_count()))print("active thread list = {}".format(threading.enumerate()))print("thread id = {}".format(threading.get_ident()))print("~~~~~~~~~~~~~")def add(x,y):time.sleep(1)showthreadinfo() #子线程中调用print(x+y)showthreadinfo() #主线程中调用time.sleep(1)t = threading.Thread(target=add,args=(4,5))t.start()print("====end===")运行结果:current thread = <_MainThread(MainThread, started 192)>main thread = <_MainThread(MainThread, started 192)>active thread count = 1active thread list = [<_MainThread(MainThread, started 192)>]thread id = 192~~~~~~~~~~~~~====end===current thread = main thread = <_MainThread(MainThread, stopped 192)>active thread count = 2active thread list = [<_MainThread(MainThread, stopped 192)>, ]thread id = 8424~~~~~~~~~~~~~9上面例子中,在主线程中只能看到存活的只有自己,因为子线程还没有启动,且它的父线程就是它自己。子线程启动时,它的名字为Thread-1,这个名字是解释器自动命名的,如果定义线程对象时添加了name="threadName",则这里显示的就是threadName;同时,子线程的父线程就是主线程,也就是说谁启动的线程谁就是它的父线程;子线程能看到的存活线程有父线程和自身。Thread实例的属性:threading.current_thread().name 线程名,只是一个标识符,可以使用getName()、setName()获取和运行时重命名。threading.current_thread().ident 线程ID,非0整数。线程启动后才会有ID,否则为None。线程退出,此ID依旧可以访问。此ID可以重复使用threading.current_thread().is_alive() 返回线程是否存活,布尔值,True或False。举例:import threadingimport timedef worker():count = 1while True:if count >= 6:breaktime.sleep(1)count += 1print("thread name = {}".format(threading.current_thread().name))t = threading.Thread(target=worker,name="MyThread")t.start()while True:time.sleep(1.1)if t.is_alive():print("{} {} alive".format(t.name,t.ident))else:print("{} {} alive".format(t.name, t.ident))t.start()print("====end===")运行结果:thread name = MyThreadMyThread 9400 alivethread name = MyThreadMyThread 9400 alivethread name = MyThreadMyThread 9400 alivethread name = MyThreadMyThread 9400 alivethread name = MyThreadMyThread 9400 aliveTraceback (most recent call last):File "C:/python/test.py", line 22, in t.start()raise RuntimeError("threads can only be started once")RuntimeError: threads can only be started once从上面例子中可以看到子线程存活时的名字和线程ID,但在线程退出后,尝试再次启动线程时,抛出RuntimeError异常,表明线程对象在定义后只能启动一次。举例 getName()和setName():import threadingimport timedef add(x,y):for _ in range(5):time.sleep(1)print("x+y={}".format(x+y))t = threading.Thread(target=add,name="MyThread",args=(6,7))t.start()while True:time.sleep(1)if t.is_alive():print("{} {} alive".format(t.name,t.ident))print("Thread name",t.getName())t.setName("MyThreadTwo")else:print("{} {} alive".format(t.name, t.ident))print("Thread abort....")break# t.start()print("====end===")运行结果:MyThread 2564 aliveThread name MyThreadx+y=13MyThreadTwo 2564 aliveThread name MyThreadTwox+y=13MyThreadTwo 2564 aliveThread name MyThreadTwox+y=13MyThreadTwo 2564 aliveThread name MyThreadTwox+y=13MyThreadTwo 2564 aliveThread name MyThreadTwox+y=13MyThreadTwo 2564 aliveThread abort....====end===上面例子演示了在运行时获取线程名和重命名线程名。线程的start()和run()方法:start():import threadingimport timedef add(x,y):for _ in range(5):time.sleep(0.5)print("x+y={}".format(x+y))class MyThread(threading.Thread):def start(self):print('start~~~~~~~~~~')super().start()def run(self):print('run~~~~~~~~~~~~')super().run() #调用父类的start()和run()方法t = MyThread(target=add,name="MyThread",args=(6,7))t.start()# t.run()print("====end===")运行结果:start~~~~~~~~~~run~~~~~~~~~~~~====end===x+y=13x+y=13x+y=13x+y=13x+y=13从上面的例子中,可以看出start()方法会先运行start()方法,再运行run()方法。跟进一下start() 方法源码中的调用过程:1、def start(self):_start_new_thread(self._bootstrap, ())....2、_start_new_thread = _thread.start_new_thread3、def start_new_thread(function, args, kwargs=None):pass4、def _bootstrap(self):self._bootstrap_inner()5、def _bootstrap_inner(self):....try:self.run()#最终start()方法调用了run()方法except SystemExit:pass从上面跟踪源码的过程大概了解了start()方法如何调用到了run()方法。run()方法:import threadingimport timedef add(x,y):for _ in range(5):time.sleep(0.5)print("x+y={}".format(x+y))class MyThread(threading.Thread):def start(self):print('start~~~~~~~~~~')super().start()def run(self):print('run~~~~~~~~~~~~')super().run() #调用父类的start()和run()方法t = MyThread(target=add,name="MyThread",args=(6,7))# t.start()t.run()print("====end===")运行结果:run~~~~~~~~~~~~x+y=13x+y=13x+y=13x+y=13x+y=13====end===上面例子中,运行线程的run()方法只能调用到run()方法。跟踪一下run() 方法在源码中的调用过程:1、def __init__(self, group=None, target=None, name=None,args=(), kwargs=None, *, daemon=None):self._target = targetself._args = argsself._kwargs = kwargs....2、def run(self):if self._target:self._target(*self._args, **self._kwargs)....可以看出,_target是我们传入的目标函数,run()方法其实就类似一个装饰器,最终还是将_args 和_kwargs 参数传入目标函数运行,返回结果。start() --> run() --> _target()run() --> _target()上面两个例子简单介绍了start()方法和run()方法的调用,下一篇文章再详细看一下它们到底有什么区别。总结:本文主要介绍了: Thread类、线程启动、线程的传参、线程退出、threading属性、Thread实例的属性、举例getName()和setName()、线程的start()和run()方法

我要回帖

更多关于 java主线程结束,子线程还能运行么 的文章

 

随机推荐