关键词搜索

源码搜索 ×
×

一篇文章带你搞定 Java 中多线程的实现(Thread,Runnable)

发布2020-01-16浏览617次

详情内容

Java 中要想实现多线程代码有两种手段,一种是继承 Thread 类,另一种就是实现 Runnable 接口

开发工程中,建议使用 Runnable 接口实现多线程

一、继承 Thread 类

Thread 类是在 java.lang 包中定义的,一个类只要继承了 Thread 类,此类就称为多线程操作类。在 Thread 子类中,必须明确复写 Thread 类中的 run() 方法,此方法为线程的主体

class 类名称 extends Thread{//继承 Thread 类
	属性;//类中定义属性
	方法;//类中定义方法
	public void run(){//覆写 Thread 类中的 run() 方法,此方法时线程的主体
		线程主体;
	}
}

    程序的调用从 Thread 类中继承而来的 start() 方法,而不是 run()方法。

    class MyThread extends Thread{//继承 Thread 类
        private String name;
        public MyThread(String name){
            this.name = name;
        }
        public void run(){//覆写 Thread 类中的 run() 方法
            for(int i=0;i<10;i++){//循环 10 次输出
                System.out.println(name + "运行,i = " + i);
            }
        }
    }
    
    public class Root{
        public static void main(String[] args) {
            MyThread mt1 = new MyThread("线程 A");//实例化对象
            MyThread mt2 = new MyThread("线程 B");//实例化对象
            mt1.start();//启动多线程
            mt2.start();//启动多线程
        }
    }
    
      8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述
    由结果(可能结果的一种)可知,两个线程现在是交错运行,哪个线程对象抢到了 CPU资源,哪个线程就可以运行,所以程序每次的运行结果肯定是不一样的,在线程启动时虽然是调用的是 start() 方法,但是实际上调用的却是 run() 方法的主

    如果一个类通过继承 Thread 类来实现,那么只能调用一次 start() 方法,如果调用多次,则将会抛出“IllegalThreadStateException” 异常

    多线程的实现需要依靠底层操作系统支持

    二、实现 Runnable 接口

    在 Java 中也可以通过实现 Runnable 接口的方式实现多线程,Runnable 接口中只定义了一个抽象方法:

    public void run();
    
    • 1

    使用 Runnable 接口实现多线程的格式如下:

    class 类名称 implements Runnable{//实现 Runnable 接口
    	属性...;
    	方法...;
    	public void run(){//覆写 Runnable 接口中的 run() 方法
    		线程主体;
    	}
    }
    

      示例:

      class MyThread implements Runnable{//继承 Runnable 接口
          private String name;
          public MyThread(String name){
              this.name = name;
          }
          public void run(){//覆写 Thread 类中的 run() 方法
              for(int i=0;i<5;i++){//循环 10 次输出
                  System.out.println(name + "运行,i = " + i);
              }
          }
      }
      
        8
      • 9
      • 10
      • 11

      这里通过 Runnable 接口实现了多线程,如果想要实现 Runnable 接口,还是要依靠 Thread 类完成启动,在 Thread 类中提供了
      public Thread(Runnable target)public Thread(Runnable target,String name) 两个构造方法。

      这两个构造方法都可以接收 Runnable 的子类实例对象,所以就可以依靠此点启动多线程:

      class MyThread implements Runnable{//继承 Runnable 接口
          private String name;
          public MyThread(String name){
              this.name = name;
          }
          public void run(){//覆写  run() 方法
              for(int i=0;i<5;i++){//循环 10 次输出
                  System.out.println(name + "运行,i = " + i);
              }
          }
      }
      public class Root{
          public static void main(String[] args) {
              MyThread my1 = new MyThread("线程 A");//实例化Runnable子类对象
              MyThread my2 = new MyThread("线程 B");//实例化Runnable子类对象
              Thread t1 = new Thread(my1);//实例化 Thread 类对象
              Thread t2 = new Thread(my2);//实例化 Thread 类对象
              t1.start();//启动多线程
              t2.start();//启动多线程
          }
      }
      
        8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21

      在这里插入图片描述

      三、Thread 类和 Runnable 接口

      如果一个类继承 Thread 类,则不适合于多个线程共享资源,而实现了 Runnable 接口,就可以方便地实现资源的共享

      1. 继承 Thread 类不能资源共享
      class MyThread extends Thread{//继承 Thread 类
          private int ticket = 5;//一共 5 张票
          public void run(){//覆写 Thread 类中的 run() 方法
              for(int i=0;i<10;i++){//超出票数的循环
                  if(ticket>0){//判断是否有剩余票
                      System.out.println("卖票:ticket = " + ticket--);
                  }
              }
          }
      }
      
      public class Root{
          public static void main(String[] args) {
              MyThread mt1 = new MyThread();//定义线程对象
              MyThread mt2 = new MyThread();//定义线程对象
              MyThread mt3 = new MyThread();//定义线程对象
              mt1.start();//启动第 1 个线程
              mt2.start();//启动第 2 个线程
              mt3.start();//启动第 3 个线程
          }
      }
      
        8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21

      在这里插入图片描述
      程序通过 Thread 类实现多线程,程序中启动了 3 个线程,但是 3 个线程却分别卖了各自的 5 张票,并没有达到资源共享的目的。

      这里也不能像 Runnable 一样实例化一个,启动两个start,因为如果一个类通过继承 Thread 类来实现,那么只能调用一次 start() 方法,否则就会报错。
      错误的代码

      public class Root{
          public static void main(String[] args) {
              MyThread mt1 = new MyThread();//定义线程对象
              mt1.start();//启动第 1 个线程
              mt1.start();//启动第 1 个线程
          }
      }
      
        1. 实现 Runnable 接口可以资源共享
        class MyThread implements Runnable{//继承 Runnable 接口
            private int ticket = 5;//一共 5 张票
            public void run(){//覆写 Thread 类中的 run() 方法
                for(int i=0;i<10;i++){//超出票数的循环
                    if(ticket>0){//判断是否有剩余票
                        System.out.println("卖票:ticket = " + ticket--);
                    }
                }
            }
        }
        
        public class Root{
            public static void main(String[] args) {
                MyThread my = new MyThread();//定义线程对象
                //启动两个线程来完成这个线程对象
                new Thread(my).start();//启动第 1 个线程
                new Thread(my).start();//启动第 2 个线程
            }
        }
        
          8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19

        在这里插入图片描述
        这里的意思是实例化一个线程对象,通过两个线程同时去执行它,这个过程中还是通过 Thread 来启动多个线程的。

        Runnable 接口相对于继承 Thread 类的优势

        • 适合多个相同程序代码的线程去处理同一资源的情况
        • 可以避免由于 Java 的单继承特性带来的局限
        • 增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的

        相关技术文章

        点击QQ咨询
        开通会员
        返回顶部
        ×
        微信扫码支付
        微信扫码支付
        确定支付下载
        请使用微信描二维码支付
        ×

        提示信息

        ×

        选择支付方式

        • 微信支付
        • 支付宝付款
        确定支付下载