Java提供了线程类Thread来创建多线程的程序。其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象。每个Thread对象描述了一个单独的线程。要产生一个线程,有两种方法:

◆需要从Java.lang.Thread类派生一个新的线程类,重载它的run()方法;

◆实现Runnalbe接口,重载Runnalbe接口中的run()方法。

为什么Java要提供两种方法来创建线程呢?它们都有哪些区别?相比而言,哪一种方法更好呢?

在Java中,类仅支持单继承,也就是说,当定义一个新的类的时候,它只能扩展一个外部类.这样,如果创建自定义线程类的时候是通过扩展 Thread类的方法来实现的,那么这个自定义类就不能再去扩展其他的类,也就无法实现更加复杂的功能。因此,如果自定义类必须扩展其他的类,那么就可以使用实现Runnable接口的方法来定义该类为线程类,这样就可以避免Java单继承所带来的局限性。

还有一点最重要的就是使用实现Runnable接口的方式创建的线程可以处理同一资源,从而实现资源的共享.

(1)通过扩展Thread类来创建多线程

假设一个影院有三个售票口,分别用于向儿童、成人和老人售票。影院为每个窗口放有100张电影票,分别是儿童票、成人票和老人票。三个窗口需要同时卖票,而现在只有一个售票员,这个售票员就相当于一个CPU,三个窗口就相当于三个线程。通过程序来看一看是如何创建这三个线程的。

public class MutliThreadDemo {
    public static void main(String [] args){
        MutliThread m1=new MutliThread("Window 1");
        MutliThread m2=new MutliThread("Window 2");
        MutliThread m3=new MutliThread("Window 3");
        m1.start();
        m2.start();
        m3.start();
    }
}
class MutliThread extends Thread{
    private int ticket=100;//每个线程都拥有100张票
    MutliThread(String name){
        super(name);//调用父类带参数的构造方法
    }
    public void run(){
        while(ticket>0){
            System.out.println(ticket--+" is saled by "+Thread.currentThread().getName());
        }
    }
}

结果显示:
100 is saled by Window 2
100 is saled by Window 1
99 is saled by Window 1
98 is saled by Window 1
97 is saled by Window 1
96 is saled by Window 1
95 is saled by Window 1
94 is saled by Window 1
93 is saled by Window 1
92 is saled by Window 1
91 is saled by Window 1 
100 is saled by Window 3 
         ......
         ......

程序中定义一个线程类,它扩展了Thread类。利用扩展的线程类在MutliThreadDemo类的主方法中创建了三个线程对象,并通过start()方法分别将它们启动。

从结果可以看到,每个线程分别对应100张电影票,之间并无任何关系,这就说明每个线程之间是平等的,没有优先级关系,因此都有机会得到CPU的处理。但是结果显示这三个线程并不是依次交替执行,而是在三个线程同时被执行的情况下,有的线程被分配时间片的机会多,票被提前卖完,而有的线程被分配时间片的机会比较少,票迟一些卖完。

可见,利用扩展Thread类创建的多个线程,虽然执行的是相同的代码,但彼此相互独立,且各自拥有自己的资源,互不干扰。

(2)通过实现Runnable接口来创建多线程

public class MutliThreadDemo2 {
    public static void main(String [] args){
        MutliThread m1=new MutliThread("Window 1");
        MutliThread m2=new MutliThread("Window 2");
        MutliThread m3=new MutliThread("Window 3");
        Thread t1=new Thread(m1);
        Thread t2=new Thread(m2);
        Thread t3=new Thread(m3);
        t1.start();
        t2.start();
        t3.start();
    }
}
class MutliThread implements Runnable{
    private int ticket=100;//每个线程都拥有100张票
    private String name;
    MutliThread(String name){
        this.name=name;
    }
    public void run(){
        while(ticket>0){
            System.out.println(ticket--+" is saled by "+name);
        }
    }
}

由于这三个线程也是彼此独立,各自拥有自己的资源,即100张电影票,因此程序输出的结果和(1)结果大同小异。均是各自线程对自己的100张票进行单独的处理,互不影响。

可见,只要现实的情况要求保证新建线程彼此相互独立,各自拥有资源,且互不干扰,采用哪个方式来创建多线程都是可以的。因为这两种方式创建的多线程程序能够实现相同的功能。

由于这三个线程也是彼此独立,各自拥有自己的资源,即100张电影票,因此程序输出的结果和例4.2.1的结果大同小异。均是各自线程对自己的100张票进行单独的处理,互不影响。

可见,只要现实的情况要求保证新建线程彼此相互独立,各自拥有资源,且互不干扰,采用哪个方式来创建多线程都是可以的。因为这两种方式创建的多线程程序能够实现相同的功能。

(3)通过实现Runnable接口来实现线程间的资源共享

现实中也存在这样的情况,比如模拟一个火车站的售票系统,假如当日从A地发往B地的火车票只有100张,且允许所有窗口卖这100张票,那么每一个窗口也相当于一个线程,但是这时和前面的例子不同之处就在于所有线程处理的资源是同一个资源,即100张车票。如果还用前面的方式来创建线程显然是无法实现的,这种情况该怎样处理呢?看下面这个程序,程序代码如下所示:

public class MutliThreadDemo3 {
    public static void main(String [] args){
        MutliThread m=new MutliThread();
        Thread t1=new Thread(m,"Window 1");
        Thread t2=new Thread(m,"Window 2");
        Thread t3=new Thread(m,"Window 3");
        t1.start();
        t2.start();
        t3.start();
    }
}
class MutliThread implements Runnable{
    private int ticket=100;//每个线程都拥有100张票
    public void run(){
        while(ticket>0){
            System.out.println(ticket--+" is saled by "+Thread.currentThread().getName());
        }
    }
}
100 is saled by window1-1
97 is saled by window1-1
98 is saled by window1-3
99 is saled by window1-2
95 is saled by window1-3
96 is saled by window1-1
93 is saled by window1-3
94 is saled by window1-2
91 is saled by window1-3
92 is saled by window1-1
89 is saled by window1-3
    .......... 

结果正如前面分析的那样,程序在内存中仅创建了一个资源,而新建的三个线程都是基于访问这同一资源的,并且由于每个线程上所运行的是相同的代码,因此它们执行的功能也是相同的。

可见,如果现实问题中要求必须创建多个线程来执行同一任务,而且这多个线程之间还将共享同一个资源,那么就可以使用实现Runnable接口的方式来创建多线程程序。而这一功能通过扩展Thread类是无法实现的,读者想想看,为什么?

实现Runnable接口相对于扩展Thread类来说,具有无可比拟的优势。这种方式不仅有利于程序的健壮性,使代码能够被多个线程共享,而且代码和数据资源相对独立,从而特别适合多个具有相同代码的线程去处理同一资源的情况。这样一来,线程、代码和数据资源三者有效分离,很好地体现了面向对象程序设计的思想。因此,几乎所有的多线程程序都是通过实现Runnable接口的方式来完成的。

Java Thread中, join() 方法主要是让调用该方法的thread完成run方法里面的东西后, 再执行join()方法后面的代

Java创建线程Thread的两个方法相关推荐

  1. java创建线程常用的两种方式

    一.继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代 表了线程要完成的任务.因此把run()方法称为执行体. (2)创建Thread子类的 ...

  2. java创建线程的两种方法是_java创建线程的两种方法

    要产生一个线程,有两种方法: ◆需要从Java.lang.Thread类派生一个新的线程类,重载它的run()方法: ◆实现Runnalbe接口,重载Runnalbe接口中的run()方法. 哪种方法 ...

  3. Java创建线程的两个方法

    Java提供了线程类Thread来创建多线程的程序.其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象.每个Thread对象描述了一个单独的线程.要产生一个线 ...

  4. Java创建线程的七种方法,全网最全面总结~

    目录 前言 一.继承Thread,重写run方法 二.实现Runnable接口,重写run方法 三.使用匿名内部类创建 Thread 子类对象 四.使用匿名内部类,实现Runnable接口 五.lam ...

  5. JAVA中创建线程池的五种方法及比较

    之前写过JAVA中创建线程的三种方法及比较.这次来说说线程池. JAVA中创建线程池主要有两类方法,一类是通过Executors工厂类提供的方法,该类提供了4种不同的线程池可供使用.另一类是通过Thr ...

  6. java创建线程(Thread)的5种方式

    java创建线程(Thread)的5种方式 方式一:继承于Thread类 方式二:实现Runnable接口 方式三:实现Callable接口 方式四:使用线程池 方式五:使用匿名类 方式一:继承于Th ...

  7. Java 创建线程的三种方法比较

    在学习编程的过程中,我觉得不止要获得课本的知识,更多的是通过学习技术知识提高解决问题的能力,这样我们才能走在最前方,本文主要讲述Java 创建线程的三种方法比较, 更多Java专业知识,广州疯狂jav ...

  8. java创建线程代码_Java创建与结束线程代码示例

    本文讲述了在Java中如何创建和结束线程的最基本方法,只针对于Java初学者.一些高级知识如线程同步.调度.线程池等内容将会在后续章节中逐步深入. 创建线程 创建普通线程有两种方式,继承Thread类 ...

  9. Java 创建线程的三种方式

    一.继承Thread类创建 1.定义一个类继承Thread类,并重写Thread类的run()方法,run()方法的方法体就是线程要完成的任务,因此把run()称为线程的执行体: 2.创建该类的实例对 ...

最新文章

  1. 共享文件时提示“将安全性信息应用到以下对象时发生错误”
  2. 【143】360云盘资源
  3. Interpreter(解释器)--类行为型模式
  4. Antd-Select组件的深入用法
  5. 【sping揭秘】19、关于spring中jdbctemplate中的DataSource怎么来呢
  6. mysql 字符串出现问题_MYSQL 中字符串函数 归纳总结
  7. Android内核开发:为什么刷机后系统第一次启动会很慢?
  8. 如何在网上隐藏自己的IP地址(转)
  9. 如何最简单把pdf转换word格式
  10. OpenGL ES 理解纹理与纹理过滤
  11. 计算机英特尔显卡在哪找,英特尔®显卡和 Windows 7 * 常见问题解答
  12. 【笔记】2022.06.20 python数据分析三大神器numpy、pandas、matplotlib
  13. C++ 纯WIN32 API编程 悦读器实战示例
  14. 利用身份证号码算年龄 并排序
  15. 机械键盘各类轴的区别
  16. [运放滤波器]3_反相同相比例放大电路_Multisim电路仿真
  17. TMS320F28379D——时钟系统
  18. mfc中如何使用全局变量进行数据共享
  19. 天下文章一大抄看你会抄不会抄devGridView凭证金额录入(万仟百拾元)
  20. 人工智能写作产品解决的痛点

热门文章

  1. 详解sorted与sort用法
  2. 神州设备OSPF虚链路的配置实例1
  3. PDF 压缩常用方法比较
  4. AutoCAD Electrical 2022—项目中新建、添加、删除图纸
  5. 如何从Matlab的fig文件中把数据导出来?
  6. 【2023年第十一届泰迪杯数据挖掘挑战赛】C题:泰迪内推平台招聘与求职双向推荐系统构建 建模及python代码详解 问题一
  7. Robot接口测试post请求(form/json格式)
  8. modelsim10.1C 第一次安装打开就报错显示license故障
  9. 桌面计算机图标怎么调出来,电脑桌面图标隐藏了怎么弄出来
  10. arcgis python脚本修改属性表_Arcgis属性表修改