您好,欢迎访问三七文档
1.纲要a)多线程的基本概念b)线程的创建和启动c)线程的生命周期d)线程的调度e)线程控制f)线程的同步g)守护线程h)定时器的使用i)windows的任务计划2.内容2.1、多线程的基本概念线程指进程中的一个执行场景,也就是执行流程,那么进程和线程有什么区别呢?每个进程是一个应用程序,都有独立的内存空间同一个进程中的线程共享其进程中的内存和资源2.2、线程的创建和启动Java虚拟机的主线程入口是main方法,用户可以自己创建线程,创建方式有两种:继承Thread类实现Runnable接口(推荐使用Runnable接口)2.1.1、继承Thread类Thread类中创建线程最重要的两个方法为:publicvoidrun()publicvoidstart()采用Thread类创建线程,用户只需要继承Thread,覆盖Thread中的run方法,父类Thread中的run方法没有抛出异常,那么子类也不能抛出异常,最后采用start启动线程即可【示例代码】,不使用线程publicclassThreadTest01{publicstaticvoidmain(String[]args){Processorp=newProcessor();p.run();method1();}privatestaticvoidmethod1(){System.out.println(--------method1()----------);}}classProcessor{publicvoidrun(){for(inti=0;i10;i++){System.out.println(i);}}}以上顺序输出相应的结果(属于串行),也就是run方法完全执行完成后,才执行method1方法,也就是method1必须等待前面的方法返回才可以得到执行,这是一种“同步编程模型”【代码示例】,使用线程publicclassThreadTest02{publicstaticvoidmain(String[]args){Processorp=newProcessor();//手动调用该方法//不能采用run来启动一个场景(线程),//run就是一个普通方法调用//p.run();//采用start启动线程,不是直接调用run//start不是马上执行线程,而是使线程进入就绪//线程的真正执行是由Java的线程调度机制完成的p.start();//只能启动一次//p.start();method1();}privatestaticvoidmethod1(){System.out.println(--------method1()----------);}}classProcessorextendsThread{//覆盖Thread中的run方法,该方法没有异常//该方法是由java线程掉机制调用的//我们不应该手动调用该方法publicvoidrun(){for(inti=0;i10;i++){System.out.println(i);}}}通过输出结果大家会看到,没有顺序执行,而在输出数字的同时执行了method1()方法,如果从效率上看,采用多线程的示例要快些,因为我们可以看作他是同时执行的,mthod1()方法没有等待前面的操作完成才执行,这叫“异步编程模型”2.1.2、实现Runnable接口其实Thread对象本身就实现了Runnable接口,但一般建议直接使用Runnable接口来写多线程程序,因为接口会比类带来更多的好处【示例代码】publicclassThreadTest03{publicstaticvoidmain(String[]args){//Processorr1=newProcessor();Runnabler1=newProcessor();//不能直接调用run//p.run();Threadt1=newThread(r1);//启动线程t1.start();method1();}privatestaticvoidmethod1(){System.out.println(--------method1()----------);}}//实现Runnable接口classProcessorimplementsRunnable{//实现Runnable中的run方法publicvoidrun(){for(inti=0;i10;i++){System.out.println(i);}}}2.3、线程的生命周期线程的生命周期存在五个状态:新建、就绪、运行、阻塞、死亡新建就绪状态start运行状态终止阻塞状态线程调度阻塞事件阻塞解除新建:采用new语句创建完成就绪:执行start后运行:占用CPU时间阻塞:执行了wait语句、执行了sleep语句和等待某个对象锁,IO处理终止:退出run()方法有的书籍上对线程的生命周期是做如下定义的。Runnable可运行状态start线程启动新建终止Notrunnable阻塞状态2.4、线程的调度与控制通常我们的计算机只有一个CPU,CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。在单CPU的机器上线程不是并行运行的,只有在多个CPU上线程才可以并行运行。Java虚拟机要负责线程的调度,取得CPU的使用权,目前有两种调度模型:分时调度模型和抢占式调度模型,Java使用抢占式调度模型。分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个2.4.1、线程优先级线程优先级主要分三种:MAX_PRIORITY(最高级);MIN_PRIORITY(最低级)NOM_PRIORITY(标准)默认publicclassThreadTest04{publicstaticvoidmain(String[]args){Runnabler1=newProcessor();Threadt1=newThread(r1,t1);//设置线程的优先级,线程启动后不能再次设置优先级//必须在启动前设置优先级//设置最高优先级t1.setPriority(Thread.MAX_PRIORITY);//启动线程t1.start();//取得线程名称//System.out.println(t1.getName());Threadt2=newThread(r1,t2);//设置最低优先级t2.setPriority(Thread.MIN_PRIORITY);t2.start();System.out.println(Thread.currentThread().getName());}}classProcessorimplementsRunnable{publicvoidrun(){for(inti=0;i100;i++){System.out.println(Thread.currentThread().getName()+,+i);}}}从以上输出结果应该看可以看出,优先级高的线程(t1)会得到的CPU时间多一些,优先执行完成2.4.2、Thread.sleepsleep设置休眠的时间,单位毫秒,当一个线程遇到sleep的时候,就会睡眠,进入到阻塞状态,放弃CPU,腾出cpu时间片,给其他线程用,所以在开发中通常我们会这样做,使其他的线程能够取得CPU时间片,当睡眠时间到达了,线程会进入就绪状态,得到CPU时间片继续执行,如果线程在睡眠状态被中断了,将会抛出IterruptedException【示例代码】publicclassThreadTest05{publicstaticvoidmain(String[]args){Runnabler1=newProcessor();Threadt1=newThread(r1,t1);t1.start();Threadt2=newThread(r1,t2);t2.start();}}classProcessorimplementsRunnable{publicvoidrun(){for(inti=0;i100;i++){System.out.println(Thread.currentThread().getName()+,+i);if(i%10==0){try{//睡眠100毫秒,主要是放弃CPU的使用,将CPU时间片交给其他线程使用Thread.sleep(100);}catch(InterruptedExceptione){e.printStackTrace();}}}}}2.4.3、Thread.yield、它与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会publicclassThreadTest06{publicstaticvoidmain(String[]args){Runnabler1=newProcessor();Threadt1=newThread(r1,t1);t1.start();Threadt2=newThread(r1,t2);t2.start();}}classProcessorimplementsRunnable{publicvoidrun(){for(inti=0;i100;i++){System.out.println(Thread.currentThread().getName()+,+i);if(i%10==0){System.out.println(--------------);//采用yieid可以将CPU的使用权让给同一个优先级的线程Thread.yield();}}}}2.4.4、Thread.join当前线程可以调用另一个线程的join方法,调用后当前线程会被阻塞不再执行,直到被调用的线程执行完毕,当前线程才会执行publicclassThreadTest07{publicstaticvoidmain(String[]args){Runnabler1=newProcessor();Threadt1=newThread(r1,t1);t1.start();try{t1.join();}catch(InterruptedExceptione){e.printStackTrace();}System.out.println(------mainend-------);}}classProcessorimplementsRunnable{publicvoidrun(){for(inti=0;i10;i++){System.out.println(Thread.currentThread().getName()+,+i);}}}2.4.5、interrupt(中断)如果我们的线程正在睡眠,可以采用interrupt进行中断publicclassThreadTest08{publicstaticvoidmain(String[]args){Runnabler1=newProcessor();Threadt1=newThread(r1,t1);t1.start();try{//设置为500毫秒,没有出现中断异常,因为//500毫秒之后再次调用t1.interrupt()时,//此时的睡眠线程已经执行完成//如果sleep的时间设置的小一些,会出现中断异常,//因为存在睡眠线程Thread.sleep(500);}catch(Exceptione){e.printStackTrace();}//中断睡眠中的线程t1.interrupt();}}classProcessorimplementsRunnable{publicvoidrun(){for(inti=1;i100;i++){System.out.println(Thread.currentThread().getName()+,+i);if(i%50==0){
本文标题:09-多线程
链接地址:https://www.777doc.com/doc-4628321 .html