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

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

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

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

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

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

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

 1 public class MutliThreadDemo {
2 public static void main(String[] args) {
3 MutliThread m1=new MutliThread("Window 1");
4 MutliThread m2=new MutliThread("Window 2");
5 MutliThread m3=new MutliThread("Window 3");
6 m1.start();
7 m2.start();
8 m3.start();
9 }
10 }
 1 public class MutliThread extends Thread {
2 private int ticket=100;//每个线程都拥有100张票
3
4 public MutliThread (){}
5 public MutliThread (String name){
6 super(name);
7 }
8
9 @Override
10 public void run() {
11 while(ticket>0){
12 System.out.println(ticket--+" is saled by "+Thread.currentThread().getName());
13 }
14 }
15 }

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

从结果可以看到,每个线程分别对应100张电影票,之间并无任何关系,这就说明每个线程之间是平等的,没有优先级关系,因此都有机会得到CPU的处理。但是结果

显示这三个线程并不是依次交替执行,而是在三个线程同时被执行的情况下,有的线程被分配时间片的机会多,票被提前卖完,而有的线程被分配时间片的机会比较

少,票迟一些卖完。

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

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

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

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

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

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

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

 1 public class MutliThreadDemo {
2 public static void main(String[] args) {
3 MutliThread m=new MutliThread();
4 Thread t1=new Thread(m);
5 Thread t2=new Thread(m);
6 Thread t3=new Thread(m);
7 t1.start();
8 t2.start();
9 t3.start();
10 }
11 }
1 public class MutliThread implements Runnable{
2 private int ticket=100;//每个线程都拥有100张票
3 public void run(){
4 while(ticket>0){
5 System.out.println(ticket--+" is saled by "+Thread.currentThread());
6 }
7 }
8 }

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

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

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

转自:http://www.cnblogs.com/gw811/archive/2012/10/15/2724882.html

Java 创建线程的两种方法的更多相关文章

  1. Java创建线程的两种方法

    大多数情况,通过实例化一个Thread对象来创建一个线程.Java定义了两种方式: 实现Runnable 接口: 可以继承Thread类. 下面的两小节依次介绍了每一种方式. 实现Runnable接口 ...

  2. java创建线程的四种方法

    第一种:  通过继承Thread类创建线程 第二种: 通过实现Runnable接口创建线程 这两种早已烂记于心,这里就不作过多的介绍, 主要介绍其源码 Thread类 implements Runna ...

  3. java创建线程的三种方法

    这里不会贴代码,只是将创建线程的三种方法做个笼统的介绍,再根据源码添加上自己的分析. 通过三种方法可以创建java线程: 1.继承Thread类. 2.实现Runnable接口. 3.实现Callab ...

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

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

  5. java创建线程的两种方式及源码解析

    创建线程的方式有很多种,下面我们就最基本的两种方式进行说明.主要先介绍使用方式,再从源码角度进行解析. 继承Thread类的方式 实现Runnable接口的方式 这两种方式是最基本的创建线程的方式,其 ...

  6. 进程和创建线程的两种方法(threading.Thread)

    进程 如QQ 要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理, 网络接口的调用等,进程就是各种资源管理的集合 线程:是操作系统最小的调度单位,是一串指令的结合 进程 要操作 ...

  7. Java线程(一)——创建线程的两种方法

    Thread 和 Runnable Java程序是通过线程执行的,线程在程序中具有独立的执行路径.当多条线程执行时,它们之间的路径可以不同,例如,一条线程可能在执行switch的一个case语句,另一 ...

  8. 区分JAVA创建线程的几种方法

    1. start()和run()       通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行.然后 通过此Thread类调用方法run()来完成其运行操 ...

  9. Java 创建线程的3种方法及各自优势

    1. 继承 Thread 类,然后调用 start 方法. class MyThread extends Thread { //重写run方法,线程运行后,跑的就是run方法 public void ...

随机推荐

  1. 【BZOJ4403】序列统计 Lucas定理

    [BZOJ4403]序列统计 Description 给定三个正整数N.L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量.输出答案对10^6+3取模的结果. Input 输入第 ...

  2. mock数据(模拟后台数据)

    mock数据(模拟后台数据) - Emily恩 - 博客园 https://www.cnblogs.com/enboke/p/vue.html Mock.js http://mockjs.com/ 前 ...

  3. SQL语句中的Having子句与where子句

    一.介绍 聚合函数如SUM, COUNT, MAX, AVG等.这些函数和其它函数的根本区别就是它们一般作用在多条记录上.而通过使用GROUP BY 子句,可以让SUM 和 COUNT 这些函数对属于 ...

  4. MD5,SHA256,时间戳获取

    import hashlib # MD5加密 def jiamimd5(src): m = hashlib.md5() m.update(src.encode('UTF-8')) return m.h ...

  5. SingleNumber

    Given an array of integers, every element appears twice except for one. Find that single one. Note: ...

  6. CentOS Linux中zip压缩和unzip解压缩命令详解

    以下命令均在/home目录下操作cd /home  #进入/home目录1.把/home目录下面的mydata目录压缩为mydata.zip     zip -r  mydata.zip   myda ...

  7. Eclipse解决JSP页面乱码问题

    解决方案 1.首先选择 Window  -->  Preferences  -->  General-->  Content Types --> text (点击左边的+,显示 ...

  8. More about Parameter Passing in Python(Mainly about list)

    我之前写了一篇关于Python参数传递(http://www.cnblogs.com/lxw0109/p/python_parameter_passing.html)的博客, 写完之后,我发现我在使用 ...

  9. iframe与父窗口之间数据互相获取

    Js/Jquery获取iframe中的元素 博客分类: jquery javascript jquery  在web开发中,经常会用到iframe,难免会碰到需要在父窗口中使用iframe中的元素.或 ...

  10. NavigationDrawer和NavigationView-Android M新控件

    Translucent System Bars-4.4新特性 Toolbar-5.0新特性 NavigationDrawer 简介 NavigationDrawer 是 Google 在 Materi ...