黑马程序员——Java多线程

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


一、学习目标:

  • 理解程序、线程和进程的概念    
  • 理解多线程的概念    
  • 掌握线程的各种状态 
  • 熟练使用Thread类、Runnable接口创建线程 熟练使用线程各种方法  
  • 掌握线程的调度及线程同步的实现原理
二、程序、线程、进程:
   
程序:是一段静态的代码,是一段计算机指令。 
    
进程:是程序在自身地址空间中的一次动态执行。进程是资源申请、调度和和独立运行的单位,使用了CPU的资源。 

线程:是轻量级的进程,是比进程更小的执行单位,是进程的一个独立的连续控制流。一个进程的执行过程中可以产生多个线程,线程之间可以互相通信,在整个运行过    程中,多有的线程只共享一段内存空间。

三、线程的五种状态
新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread()
就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行      ,并不是说执行了t.start()此线程立即就会执行
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU  调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:
  • 等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
  • 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
  • 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

四、线程的创建:

1.继承Thread类,重写该类的run()方法。
<span style="font-family:SimSun;font-size:14px;"><span style="font-size:14px;">class MyThread extends Thread {
    
    private int i = 0;

    @Override
    public void run() {
        for (i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }
}</span></span>
<span style="font-family:SimSun;font-size:14px;"><span style="font-size:14px;">public class ThreadTest {

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            if (i == 30) {
                Thread myThread1 = new MyThread();     // 创建一个新的线程  myThread1  此线程进入新建状态
                Thread myThread2 = new MyThread();     // 创建一个新的线程 myThread2 此线程进入新建状态
                myThread1.start();                     // 调用start()方法使得线程进入就绪状态
                myThread2.start();                     // 调用start()方法使得线程进入就绪状态
            }
        }
    }
}</span></span>
如上所示,继承Thread类,通过重写run()方法定义了一个新的线程类MyThread,其中run()方法的方法体代表了线程需要完成的任务,称之为线程执行体。当创建此线程类对象时一个新的线程得以创建,并进入到线程新建状态。通过调用线程对象引用的start()方法,使得该线程进入到就绪状态,此时此线程并不一定会马上得以执行,这取决于CPU调度时机。
2.实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,   该Thread对象才是真正的线程对象。
<span style="font-family:SimSun;font-size:14px;"><span style="font-size:14px;">class MyRunnable implements Runnable {
    private int i = 0;

    @Override
    public void run() {
        for (i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }
}</span></span>
<span style="font-family:SimSun;font-size:14px;"><span style="font-size:14px;">public class ThreadTest {

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            if (i == 30) {
                Runnable myRunnable = new MyRunnable(); // 创建一个Runnable实现类的对象
                Thread thread1 = new Thread(myRunnable); // 将myRunnable作为Thread target创建新的线程
                Thread thread2 = new Thread(myRunnable);
                thread1.start(); // 调用start()方法使得线程进入就绪状态
                thread2.start();
            }
        }
    }
}</span></span>

五、线程的常用方法
设置线程名字:setName(); 获取线程名字:getName(); 
主线程默认的名字可是:main 
返回当前正在执行的线程:currentThread(); 
挂起线程:sleep();该方法要捕捉异常(InterruptedException)           Wait()后面详细讲解; 
中断线程:interrupt(); 
  终止线程:stop();不建议使用,会引起不安全问题; 
下面将上述的方法用到实际的程序中:
<span style="font-family:SimSun;font-size:14px;">public class  ThreadMethod extends Thread{     public ThreadMethod(String name){      super(name);    } 
     public void run(){ 
      Thread thread = Thread.currentThread(); 
      System.out.println("修改前线程的名字是:"+thread.getName());       thread.setName("线程B"); 
      System.out.println("修改后的线程名字是:"+thread.getName());       try{  
     System.out.println(thread.getName()+"睡眠一秒钟");      Thread.sleep(1000); 
     System.out.println(thread.getName()+"让出锁两秒钟");      wait(1000*2); 
     }catch(InterruptedException e){ 
         System.out.println(thread.getName()+"被打断了");       }    } 
     public static void main(String[] args){ 
     String name = Thread.currentThread().getName();      System.out.println(name+"开始执行"); 
</span>

检查线程:

:isALive(); 

isAlive()方法可以判断一个线程是否处于活动状态,当线程处于新建状态时,使用该方法将会返回FALSE,在线程的run方法结束之前,isAlive方法的返回值都是TRUE,当线程进入死亡状态时,该方法的返回值是FALSE;

 

线程联合:

join() 

如果一个线程需要另一个线程执行完毕,才继续执行,可以使用join方法;

  

守护线程:

setDaemon()

守护线程也称为用户线程,主要是为其他的线程提供支持。当其他非守护线程执行完毕时,java虚拟机才会停止守护线程的执行,退出程序。

 

线程的调度和优先级

设置优先级:setPriority(),参数:Thread.MAX_PRIORITY,Thread.MIN_PRIORITY,Thread.NORM_PRIORITY;


join方法实例
<span style="font-family:SimSun;font-size:14px;">public class JoinMethod extends Thread{     public void runThread(){ 
         String name = Thread.currentThread().getName(); 
         System.out.println(name+"开始执行runThread()方法");           for(int i = 0;i<5;i++){              try{ 
                      Thread.sleep(1000); 
                 }catch(InterruptedException e){} 
                System.out.println(name+"第"+i+"次执行循环体");         }      }  
    public void run(){          runThread();      } 
     public static void main(String[] args){      JoinMethod jm = new JoinMethod();       jm.setName("联合线程");     jm.start();     try{ 
        jm.join(); 
      }catch(InterruptedException e){}    } }</span>
wait方法实例
<span style="font-family:SimSun;font-size:14px;">public class WaitDemo implements Runnable{ 
    private synchronized void readString(String content){     String name =  Thread.currentThread().getName();     System.out.println(name+"开始执行");     System.out.println("当前对象"+this);     try{ 
     System.out.println(name+"等待1秒");      wait(1000*2);          Thread.sleep(1000); 
      System.out.println(name+"线程休眠了两秒");     }catch(InterruptedException e){}  
    System.out.println(name+"输出字符串");    for(int i = 0;i<content.length();i++){        System.out.print(content.charAt(i));  
       }     } 
    public void run(){ 
      String content = "心中的日月";       readString(content);   } 
     public static void main(String[] args){      WaitDemo wd = new WaitDemo();       new Thread(wd,"线程A").start();       new Thread(wd,"线程B").start();         }    }</span>

线程同步:当多个线程共同操作同一个对象时,会出现数据的混乱,要加关键字synchronized实现线程的同步。在方法前面加上    synchronized,每次只能使一个线程操作数据。
等待:当一个线程正在使用一个同步方法时,该线程会一直占用改同步方法的锁,知道执行完毕,但是可以通过wait方法使线程自动   释放同步方法的锁,这样会是线程处于就绪状态,不会监视组员使用权。 
唤醒:notify()方法,唤醒一个在此对象监视器上等待的线程;notify()唤醒所有在此对象监视器上的等待的线程。 
死锁:死锁是由于资源的无序使用带来的,解决死锁问题的方法;线程获取对象锁的顺序一致即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值