举例讲解Java中的多线程编程

 更新时间:2015年09月29日 09:32:23   投稿:goldensun  
这篇文章主要介绍了举例讲解Java中的多线程编程,线程是Java学习中的重要知识,需要的朋友可以参考下

Java创建线程(Runnable接口和Thread类)
大多数情况,通过实例化一个Thread对象来创建一个线程。Java定义了两种方式:

  1. 实现Runnable 接口;
  2. 可以继承Thread类。

下面的依次介绍了每一种方式。
实现Runnable接口

创建线程的最简单的方法就是创建一个实现Runnable 接口的类。Runnable抽象了一个执行代码单元。你可以通过实现Runnable接口的方法创建每一个对象的线程。为实现Runnable 接口,一个类仅需实现一个run()的简单方法,该方法声明如下:

  public void run( )


在run()中可以定义代码来构建新的线程。理解下面内容是至关重要的:run()方法能够像主线程那样调用其他方法,引用其他类,声明变量。仅有的不同是run()在程序中确立另一个并发的线程执行入口。当run()返回时,该线程结束。

在你已经创建了实现Runnable接口的类以后,你要在类内部实例化一个Thread类的对象。Thread 类定义了好几种构造函数。我们会用到的如下:

  Thread(Runnable threadOb, String threadName)


该构造函数中,threadOb是一个实现Runnable接口类的实例。这定义了线程执行的起点。新线程的名称由threadName定义。

建立新的线程后,它并不运行直到调用了它的start()方法,该方法在Thread 类中定义。本质上,start() 执行的是一个对run()的调用。 Start()方法声明如下:

  void start( )

下面的例子是创建一个新的线程并启动它运行:

// Create a second thread.
class NewThread implements Runnable {
  Thread t;
  NewThread() {
    // Create a new, second thread
    t = new Thread(this, "Demo Thread");
    System.out.println("Child thread: " + t);
    t.start(); // Start the thread
  }

  // This is the entry point for the second thread.
  public void run() {
    try {
      for(int i = 5; i > 0; i--) {
        System.out.println("Child Thread: " + i);
        Thread.sleep(500);
      }
    } catch (InterruptedException e) {
      System.out.println("Child interrupted.");
    }
    System.out.println("Exiting child thread.");
  }
}

class ThreadDemo {
  public static void main(String args[]) {
    new NewThread(); // create a new thread
    try {
      for(int i = 5; i > 0; i--) {
        System.out.println("Main Thread: " + i);
        Thread.sleep(1000);
      }
    } catch (InterruptedException e) {
      System.out.println("Main thread interrupted.");
    }
    System.out.println("Main thread exiting.");
  }
}

在NewThread 构造函数中,新的Thread对象由下面的语句创建::

  t = new Thread(this, "Demo Thread");


通过前面的语句this 表明在this对象中你想要新的线程调用run()方法。然后,start() 被调用,以run()方法为开始启动了线程的执行。这使子线程for 循环开始执行。调用start()之后,NewThread 的构造函数返回到main()。当主线程被恢复,它到达for 循环。两个线程继续运行,共享CPU,直到它们的循环结束。该程序的输出如下:

Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.

如前面提到的,在多线程程序中,通常主线程必须是结束运行的最后一个线程。实际上,一些老的JVM,如果主线程先于子线程结束,Java的运行时间系统就可能“挂起”。前述程序保证了主线程最后结束,因为主线程沉睡周期1000毫秒,而子线程仅为500毫秒。这就使子线程在主线程结束之前先结束。简而言之,你将看到等待线程结束的更好途径。
扩展Thread

创建线程的另一个途径是创建一个新类来扩展Thread类,然后创建该类的实例。当一个类继承Thread时,它必须重载run()方法,这个run()方法是新线程的入口。它也必须调用start()方法去启动新线程执行。下面用扩展thread类重写前面的程序:

// Create a second thread by extending Thread
class NewThread extends Thread {
  NewThread() {
    // Create a new, second thread
    super("Demo Thread");
    System.out.println("Child thread: " + this);
    start(); // Start the thread
  }

  // This is the entry point for the second thread.
  public void run() {
    try {
      for(int i = 5; i > 0; i--) {
        System.out.println("Child Thread: " + i);
        Thread.sleep(500);
      }
    } catch (InterruptedException e) {
      System.out.println("Child interrupted.");
    }
    System.out.println("Exiting child thread.");
  }
}

class ExtendThread {
  public static void main(String args[]) {
    new NewThread(); // create a new thread
    try {
      for(int i = 5; i > 0; i--) {
        System.out.println("Main Thread: " + i);
        Thread.sleep(1000);
      }
    } catch (InterruptedException e) {
      System.out.println("Main thread interrupted.");
    }
    System.out.println("Main thread exiting.");
  }
}

该程序生成和前述版本相同的输出。子线程是由实例化NewThread对象生成的,该对象从Thread类派生。注意NewThread 中super()的调用。该方法调用了下列形式的Thread构造函数:

  public Thread(String threadName)


这里,threadName指定线程名称。
选择合适方法

到这里,你一定会奇怪为什么Java有两种创建子线程的方法,哪一种更好呢。所有的问题都归于一点。Thread类定义了多种方法可以被派生类重载。对于所有的方法,惟一的必须被重载的是run()方法。这当然是实现Runnable接口所需的同样的方法。很多Java程序员认为类仅在它们被加强或修改时应该被扩展。因此,如果你不重载Thread的其他方法时,最好只实现Runnable 接口。这当然由你决定。然而,在本章的其他部分,我们应用实现runnable接口的类来创建线程。

相关文章

  • 简单学习Java+MongoDB

    简单学习Java+MongoDB

    本文给大家介绍的是如何简单的使用java+MongoDB实现数据调用的问题,非常的实用,有需要的小伙伴可以参考下
    2016-03-03
  • SpringBoot集成swagger的实例代码

    SpringBoot集成swagger的实例代码

    Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件,这篇文章主要介绍了SpringBoot集成swagger,需要的朋友可以参考下
    2017-12-12
  • 手动部署java项目到k8s中的实现

    手动部署java项目到k8s中的实现

    本文主要介绍了手动部署java项目到k8s中的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • Spring的@Conditional详解

    Spring的@Conditional详解

    这篇文章主要介绍了Spring的@Conditional详解,给想要注入Bean增加限制条件,只有满足限制条件才会被构造并注入到Spring的IOC容器中,通常和@Bean注解一起使用,需要的朋友可以参考下
    2024-01-01
  • Java中堆和栈的区别详解

    Java中堆和栈的区别详解

    这篇文章主要介绍了Java中堆和栈的区别详解,所有的Java程序都运行在JVM虚拟机内部,我们这里介绍的自然是JVM(虚拟)内存中的堆和栈,需要的朋友可以参考下
    2015-01-01
  • JAVA实现打印ascii码表代码

    JAVA实现打印ascii码表代码

    这篇文章主要介绍了JAVA实现打印ascii码表代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • JDK(免安装)各种版本下载及配置详细图文教程

    JDK(免安装)各种版本下载及配置详细图文教程

    这篇文章主要给大家介绍了关于JDK(免安装)各种版本下载及配置的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-07-07
  • 使用Java和PostgreSQL存储向量数据的实现指南

    使用Java和PostgreSQL存储向量数据的实现指南

    在当今的数字化时代,数据存储的方式和技术正变得越来越复杂和多样化,随着机器学习和数据科学的发展,向量数据的存储和管理变得尤为重要,本文将详细介绍如何使用 Java 和 PostgreSQL 数据库来存储向量数据,需要的朋友可以参考下
    2024-09-09
  • 基于Nacos实现Spring Cloud Gateway实现动态路由的方法

    基于Nacos实现Spring Cloud Gateway实现动态路由的方法

    这篇文章主要介绍了基于Nacos实现Spring Cloud Gateway实现动态路由的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • springMVC中RestTemplate传值接值方法

    springMVC中RestTemplate传值接值方法

    今天小编就为大家分享一篇springMVC中RestTemplate传值接值方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08

最新评论