多线程

概念:

1.进程:

    定义:在一个操作系统中,每个独立运行的程序都可以称为一个进程,也就是“正在运行的程序”。
    
    在多任务操作系统中,表面上看是支持进程并发执行的,但实际上这些进程并不是同时运行的。

2.线程:

    定义:每个运行的程序都是一个进程,在一个进程中还可以有多个单元同时运行,这些执行单元可以看做程序执行的一条条线索,这些线索被称为线程。

    操作系统中的每一个进程中至少存在一个线程。当一个Java程序启动时,就会产生一个进程,该进程会默认创建一个线程,在这个线程上会运行main()方法中的代码。

线程的创建:

    java中实现多线程有两种方式,一种是继承java.long包下的Thread类,覆写Thread类的run()方法,在run()方法中实现运行在线程上的代码;另一种是实现java.long.Runnable接口,同样是在 run()方法中实现运行在线程上的代码。

    1.继承Thread类创建多线程

        在学习多线程之前,先来看看我们所熟悉的单线程程序:
        Example01:
        
   
   
  1. public class Example01 {
  2. public static void main(String[] args) {
  3. MyThread myThread=new MyThread(); // 创建MyThread实例对象
  4. myThread.run(); // 调用MyThread类的run()方法
  5. while (true) { // 该循环是一个死循环,打印输出语句
  6. System.out.println("Main方法在运行");
  7. }
  8. }
  9. }
  10. class MyThread {
  11. public void run() {
  12. while (true) { // 该循环是一个死循环,打印输出语句
  13. System.out.println("MyThread类的run()方法在运行");
  14. }
  15. }
  16. }
        运行结果如下所示:
        

概念:

1.进程:

    定义:在一个操作系统中,每个独立运行的程序都可以称为一个进程,也就是“正在运行的程序”。
    
    在多任务操作系统中,表面上看是支持进程并发执行的,但实际上这些进程并不是同时运行的。

2.线程:

    定义:每个运行的程序都是一个进程,在一个进程中还可以有多个单元同时运行,这些执行单元可以看做程序执行的一条条线索,这些线索被称为线程。

    操作系统中的每一个进程中至少存在一个线程。当一个Java程序启动时,就会产生一个进程,该进程会默认创建一个线程,在这个线程上会运行main()方法中的代码。

线程的创建:

    java中实现多线程有两种方式,一种是继承java.long包下的Thread类,覆写Thread类的run()方法,在run()方法中实现运行在线程上的代码;另一种是实现java.long.Runnable接口,同样是在 run()方法中实现运行在线程上的代码。

    1.继承Thread类创建多线程

        在学习多线程之前,先来看看我们所熟悉的单线程程序:
        Example01:
        
    
    
  1. public class Example01 {
  2. public static void main(String[] args) {
  3. MyThread myThread=new MyThread(); // 创建MyThread实例对象
  4. myThread.run(); // 调用MyThread类的run()方法
  5. while (true) { // 该循环是一个死循环,打印输出语句
  6. System.out.println("Main方法在运行");
  7. }
  8. }
  9. }
  10. class MyThread {
  11. public void run() {
  12. while (true) { // 该循环是一个死循环,打印输出语句
  13. System.out.println("MyThread类的run()方法在运行");
  14. }
  15. }
  16. }
        运行结果如下所示:
        
         从上图可以看出,程序一直打印的是“MyThread类的run()方法在运行”,这是因为该程序是一个单线程程序,当调用MyThread类的run()方法时,遇到死循环,循环会一直进行。因此,MyThread类的打印语句将永远执行,而main()方法中的打印语句无法得到执行。
        如果希望上述代码中两个while循环中的打印语句能够并发执行,就需要实现多线程。
        Example02:
     
     
  1. public class Example02 {
  2. public static void main(String[] args) {
  3. MyThread myThread = new MyThread(); // 创建线程MyThread的线程对象
  4. myThread.start(); // 开启线程
  5. while (true) { // 通过死循环语句打印输出
  6. System.out.println("main()方法在运行");
  7. }
  8. }
  9. }
  10. class MyThread extends Thread {
  11. public void run() {
  12. while (true) { // 通过死循环语句打印输出
  13. System.out.println("MyThread类的run()方法在运行");
  14. }
  15. }
  16. }
运行结果如下:
 从上述结果看,两个while循环中的打印语句轮流执行了,说明该例子实现了多线程。

分析:单线程的程序在运行时,会按照代码的调用顺序进行执行。而在多线程中,main()方法和MyThread类的run()方法却可以同时运行互不影响,这正是单线程与多线程的区别。

实现Runnable接口创建多线程


    通过继承Thread类有一定局限性。因为Java中只支持单继承,一个类一旦继承了某个父类就无法再继承Thread类。为了克服这种弊端,Thread类提供了另外一种构造方法Thread(Runnable target),其中Runnable是一个接口,他只有一个run()方法。当通过 Thread(Runnable target)构造方法创建线程对象时,只需要为该方法传递一个实现了Runnable接口的实例对象,这样创建线程将调用实现了Runnable接口中的run()方法作为运行代码,而不需要调用Thread类的run()方法,接下来通过一个案例来演示如何通过实现Runnable接口的方式来创建多线程,如下所示:
Example03:
     
     
  1. public class Example03 {
  2. public static void main(String[] args) {
  3. MyThread myThread = new MyThread(); // 创建MyThread的实例对象
  4. Thread thread=new Thread(myThread); // 创建线程对象
  5. thread.start(); // 开启线程,执行线程中的run()方法
  6. while (true) {
  7. System.out.println("main()方法在运行");
  8. }
  9. }
  10. }
  11. class MyThread implements Runnable {
  12. public void run() { // 线程的代码段,当调用start()方法时,线程从此处开始执行
  13. while (true) {
  14. System.out.println("MyThread类的run()方法在运行");
  15. }
  16. }
  17. }

运行结果如下所示:
 MyThread类实现了Runnable接口,并重写了Runnable接口中的run()方法,通过Thread类的构造方法将MyThread类的实力对象作为参数传入。从运行结果看出该例实现了多线程。
        

后台线程

    对java程序来说,只要还有一个前台进程在运行,这个进程就不会结束,如果一个进程中只有后台线程云心,这个进程就会结束。这里提到的前台线程和后台线程是一种相对的概念,新创建的线程默认都是前台线程,如果某个线程对象在启动之前调用了setDeamon(true) 语句,这个线程就会变成一个后台线程。
Example04
    
    
  1. class DamonThread implements Runnable { // 创建DamonThread类,实现Runnable接口
  2. public void run() { // 实现接口中的run()方法
  3. while (true) {
  4. System.out.println(Thread.currentThread().getName()
  5. + "---is running.");
  6. }
  7. }
  8. }
  9. public class Example04 {
  10. public static void main(String[] args) {
  11. System.out.println("main线程是后台线程吗?"+ Thread.currentThread().isDaemon());//通过Thread的currentThread()方法得到当前线程对象
  12. DamonThread dt = new DamonThread(); // 创建一个DamonThread对象dt
  13. Thread t = new Thread(dt,"后台线程"); // 创建线程t共享dt资源
  14. System.out.println("t线程默认是后台线程吗? "+t.isDaemon()); // 判断是否为后台线程
  15. t.setDaemon(true); // 将线程t设置为后台线程
  16. t.start(); // 调用start()方法开启线程t
  17. for(int i=0;i<10;i++){
  18. System.out.println(i);
  19. }
  20. }
  21. }

运行结果如下所示:
 该示例演示了一个后台线程结束的过程。当开启线程t时,会执行死循环中的打印语句,但我们将线程t设置为后台线程后,当前台线程死亡后,JVM会通知后台线程。由于后台线程从接受指令到作出相应需要一段时间,因此打印了几次“后台线程---is running.”语句后,后台线程也结束了。由此说明进程中只有后台线程运行时,程序就会结束。

    注意:将某个线程设置为后台线程,必须在该线程启动之前,也就是说setDeamon()方法必须在start()方法之前调用,否则就会引发IllegalThreadStateException异常。

         从上图可以看出,程序一直打印的是“MyThread类的run()方法在运行”,这是因为该程序是一个单线程程序,当调用MyThread类的run()方法时,遇到死循环,循环会一直进行。因此,MyThread类的打印语句将永远执行,而main()方法中的打印语句无法得到执行。
        如果希望上述代码中两个while循环中的打印语句能够并发执行,就需要实现多线程。
        Example02:
    
    
  1. public class Example02 {
  2. public static void main(String[] args) {
  3. MyThread myThread = new MyThread(); // 创建线程MyThread的线程对象
  4. myThread.start(); // 开启线程
  5. while (true) { // 通过死循环语句打印输出
  6. System.out.println("main()方法在运行");
  7. }
  8. }
  9. }
  10. class MyThread extends Thread {
  11. public void run() {
  12. while (true) { // 通过死循环语句打印输出
  13. System.out.println("MyThread类的run()方法在运行");
  14. }
  15. }
  16. }
运行结果如下:
 从上述结果看,两个while循环中的打印语句轮流执行了,说明该例子实现了多线程。

分析:单线程的程序在运行时,会按照代码的调用顺序进行执行。而在多线程中,main()方法和MyThread类的run()方法却可以同时运行互不影响,这正是单线程与多线程的区别。

实现Runnable接口创建多线程


    通过继承Thread类有一定局限性。因为Java中只支持单继承,一个类一旦继承了某个父类就无法再继承Thread类。为了克服这种弊端,Thread类提供了另外一种构造方法Thread(Runnable target),其中Runnable是一个接口,他只有一个run()方法。当通过 Thread(Runnable target)构造方法创建线程对象时,只需要为该方法传递一个实现了Runnable接口的实例对象,这样创建线程将调用实现了Runnable接口中的run()方法作为运行代码,而不需要调用Thread类的run()方法,接下来通过一个案例来演示如何通过实现Runnable接口的方式来创建多线程,如下所示:
Example03:
    
    
  1. public class Example03 {
  2. public static void main(String[] args) {
  3. MyThread myThread = new MyThread(); // 创建MyThread的实例对象
  4. Thread thread=new Thread(myThread); // 创建线程对象
  5. thread.start(); // 开启线程,执行线程中的run()方法
  6. while (true) {
  7. System.out.println("main()方法在运行");
  8. }
  9. }
  10. }
  11. class MyThread implements Runnable {
  12. public void run() { // 线程的代码段,当调用start()方法时,线程从此处开始执行
  13. while (true) {
  14. System.out.println("MyThread类的run()方法在运行");
  15. }
  16. }
  17. }

运行结果如下所示:
 MyThread类实现了Runnable接口,并重写了Runnable接口中的run()方法,通过Thread类的构造方法将MyThread类的实力对象作为参数传入。从运行结果看出该例实现了多线程。
        

后台线程

    对java程序来说,只要还有一个前台进程在运行,这个进程就不会结束,如果一个进程中只有后台线程云心,这个进程就会结束。这里提到的前台线程和后台线程是一种相对的概念,新创建的线程默认都是前台线程,如果某个线程对象在启动之前调用了setDeamon(true) 语句,这个线程就会变成一个后台线程。
Example04
   
   
  1. class DamonThread implements Runnable { // 创建DamonThread类,实现Runnable接口
  2. public void run() { // 实现接口中的run()方法
  3. while (true) {
  4. System.out.println(Thread.currentThread().getName()
  5. + "---is running.");
  6. }
  7. }
  8. }
  9. public class Example04 {
  10. public static void main(String[] args) {
  11. System.out.println("main线程是后台线程吗?"+ Thread.currentThread().isDaemon());//通过Thread的currentThread()方法得到当前线程对象
  12. DamonThread dt = new DamonThread(); // 创建一个DamonThread对象dt
  13. Thread t = new Thread(dt,"后台线程"); // 创建线程t共享dt资源
  14. System.out.println("t线程默认是后台线程吗? "+t.isDaemon()); // 判断是否为后台线程
  15. t.setDaemon(true); // 将线程t设置为后台线程
  16. t.start(); // 调用start()方法开启线程t
  17. for(int i=0;i<10;i++){
  18. System.out.println(i);
  19. }
  20. }
  21. }

运行结果如下所示:
 该示例演示了一个后台线程结束的过程。当开启线程t时,会执行死循环中的打印语句,但我们将线程t设置为后台线程后,当前台线程死亡后,JVM会通知后台线程。由于后台线程从接受指令到作出相应需要一段时间,因此打印了几次“后台线程---is running.”语句后,后台线程也结束了。由此说明进程中只有后台线程运行时,程序就会结束。

    注意:将某个线程设置为后台线程,必须在该线程启动之前,也就是说setDeamon()方法必须在start()方法之前调用,否则就会引发IllegalThreadStateException异常。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值