`
NiuBilityMan
  • 浏览: 2322 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

【Java-线程】Java创建线程的两个方法

    博客分类:
  • Java
阅读更多
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());

        }

    }

}

程序中定义一个线程类,它扩展了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());

        }

    }

}

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

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

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

来源:http://www.cnblogs.com/whgw/archive/2011/10/03/2198506.html
分享到:
评论

相关推荐

    JAVA线程高级-线程按序交替执行

    - `Exchanger`则允许两个线程交换数据,每次只有一个线程可以完成交换,从而实现交替执行。 4. **线程间的通信**: - `wait()`, `notify()`, `notifyAll()`是Object类的方法,用于线程间的通信。一个线程调用`...

    经典Java --线程

    死锁:当两个或更多线程互相等待对方释放资源而形成的一种僵局。避免死锁的方法包括资源预分配、避免环路等待、设置超时和死锁检测恢复机制。 线程优先级:Java线程有10个优先级(1-10,其中1是最低优先级,10是...

    JAVA-多线程 所有文件

    4. **线程状态**:Java线程有五种状态:新建、就绪、运行、阻塞和终止。了解这些状态有助于理解线程的生命周期。 5. **同步机制**:Java提供了多种同步机制防止数据竞争,如`synchronized`关键字、`wait()`, `...

    JAVA-线程的入门记录

    - 当两个或多个线程无限期地等待彼此持有的锁时发生。 - 避免死锁的方法包括: - 使用锁顺序一致。 - 使用定时锁尝试。 - 使用死锁检测算法。 2. **生产者消费者模式**: - 通过**等待-唤醒机制**协调生产和...

    java编程 ---线程

    在Java中,有两种主要方式创建线程:继承`Thread`类或实现`Runnable`接口。启动线程通常通过调用`start()`方法,该方法会自动调用线程的`run()`方法。线程调度由操作系统负责,Java提供了一些控制线程优先级和同步的...

    在Java中创建线程有两种方法

    多线程程序至少需要两个线程:主线程和至少一个由用户创建的线程。主线程通常负责初始化和协调其他线程的工作。 总的来说,选择继承`Thread`还是实现`Runnable`取决于你的需求。如果你需要对线程类进行扩展或者线程...

    java中创建线程两个方法及区别

    Java提供了多种创建线程的方式,其中最常见的是通过继承`Thread`类和实现`Runnable`接口这两种方法。下面将详细阐述这两种创建线程的方法及其区别。 ### 一、通过继承`Thread`类创建线程 当一个类继承了`Thread`类...

    Java的多线程-线程间的通信.doc

    - 这两个方法在早期的Java版本中使用,但现在已被弃用,因为它们可能导致死锁。`suspend()`会让线程进入停滞状态,但不会释放锁,而`resume()`只能唤醒与之对应的`suspend()`调用的线程。这种设计容易导致其他线程...

    Java-Java线程编程教程

    Java线程编程是Java开发中的重要组成部分,尤其在如今并发处理和高性能系统设计中不可或缺。本教程将深入探讨Java多线程的相关概念、原理及实战技巧。 首先,我们需要理解什么是线程。线程是程序执行的基本单元,一...

    JAVA-JavaThreadProgramming-Sams.zip_JAVA 设计_java 多线程_java 线程_多线程

    Java线程编程是Java开发中的重要组成部分,尤其在构建高性能、高并发的应用程序时不可或缺。本资料"JAVA-JavaThreadProgramming-Sams.zip"提供了一套详细的教程,旨在深入讲解Java中的多线程设计和实现。 Java多...

    java多线程代码案例(创建线程,主线程,线程优先级,线程组,线程同步,线程间的通信)

    死锁是两个或多个线程相互等待对方释放资源,导致所有线程都无法继续执行的状态。避免死锁的关键是遵循死锁的四个必要条件:互斥、请求与保持、不剥夺和环路等待。合理设计资源获取顺序和使用`Lock`的超时、tryLock...

    java常见面试题---线程篇

    - 当两个或更多线程相互等待对方释放资源,导致都无法继续执行的状态。 - 避免死锁的关键在于避免循环等待条件,正确使用锁顺序和超时策略。 5. **线程池**: - `ExecutorService`接口和`ThreadPoolExecutor`类...

    java多线程编程 在主线程main中创建两个子线程

    自己学着编写的一个JAVA多线程程序,该程序实现的功能是:在主线程main中创建两个子线程,A和B,线程A先运行,再运行B线程,当两个子线程都运行完毕后,才运行主线程,并最终结束整个程序的运行。 希望该程序对初学...

    java多线程Demo

    Java线程有10个优先级(MIN_PRIORITY, NORM_PRIORITY, MAX_PRIORITY),默认优先级是NORM_PRIORITY。但是,线程优先级并不保证绝对的执行顺序,操作系统调度策略可能影响实际执行顺序。 7. join()方法: 一个线程...

    Java多线程-JDK5.0新增线程创建方式

    通过以上两个新增的线程创建方式,我们可以看到Java 5.0版本在多线程编程方面的改进和增强。使用`Callable`接口和线程池不仅提高了线程管理的灵活性,还增强了程序的可扩展性和性能表现。在实际开发过程中,根据具体...

    java多线程的讲解和实战

    7. **死锁与活锁**:当两个或更多线程互相等待对方释放资源而无法继续执行时,就会发生死锁。活锁则是线程虽然没有阻塞,但由于某种原因无法执行,如不断尝试获取资源。避免死锁和活锁的关键在于设计良好的同步策略...

    Java实现的两个线程同时运行案例

    在main方法中,我们创建了两个线程,t1和t2,并将它们start()以启动它们。这样,两个线程就可以同时运行了。 本文中,我们还提供了一些相关的Java多线程编程技巧,例如使用Thread.sleep()方法来暂停线程的执行,...

    java程序 两个线程实现学生成绩的读写

    为了启动这两个线程,我们会在主程序中创建它们的实例,然后调用`start()`方法。线程的执行顺序取决于JVM的调度策略,因此可能读线程先执行,也可能写线程先执行。为了避免混乱,可能需要设定一些同步规则,比如使用...

    java用线程两种方式

    在这个main方法中,程序通过两种方式创建了两个线程:一个打印1到1000之间的所有奇数,另一个打印所有偶数。通过使用while循环,程序会持续运行直到两个线程都完成了它们的任务。 总结来说,Java通过两种方式提供了...

    java多线程经典案例

    例如,一个典型的例子可能是银行转账,两个线程分别代表不同的账户,它们都需要访问账户余额这一共享资源。在转账过程中,需要先锁定账户,进行转账操作,然后解锁,这需要用到线程同步。而线程通信可能体现在当一个...

Global site tag (gtag.js) - Google Analytics