Java 多线程实现的三种方式

这篇具有很好参考价值的文章主要介绍了Java 多线程实现的三种方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java 多线程实现的三种方式

Java 多线程实现方式主要有三种:继承 Thread 类、实现 Runnable 接口、使用 ExecutorService、Callable、Future 实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。

1、继承 Thread 类实现多线程

继承 Thread 类的方法尽管被我列为一种多线程实现方式,但 Thread 本质上也是实现了 Runnable 接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过 Thread 类的 start () 实例方法。start () 方法是一个 native 方法,它将启动一个新线程,并执行 run () 方法。这种方式实现多线程很简单,通过自己的类直接 extend Thread,并复写 run () 方法,就可以启动新线程并执行自己定义的 run () 方法。例如:

1 public class MyThread extends Thread { 
2   public void run() { 
3    System.out.println("MyThread.run()"); 
4   } 
5 }

在合适的地方启动线程如下:

MyThread myThread1 = new MyThread(); 
MyThread myThread2 = new MyThread(); 
myThread1.start(); 
myThread2.start();

2、实现 Runnable 接口方式实现多线程

如果自己的类已经 extends 另一个类,就无法直接 extends Thread,此时,必须实现一个 Runnable 接口,如下:

public class MyThread extends OtherClass implements Runnable { 
  public void run() { 
   System.out.println("MyThread.run()"); 
  } 
}

为了启动 MyThread,需要首先实例化一个 Thread,并传入自己的 MyThread 实例:

MyThread myThread = new MyThread(); 
Thread thread = new Thread(myThread); 
thread.start();

事实上,当传入一个 Runnable target 参数给 Thread 后,Thread 的 run () 方法就会调用 target.run (),参考 JDK 源代码:

public void run() { 
  if (target != null) { 
   target.run(); 
  } 
}

3、使用 ExecutorService、Callable、Future 实现有返回结果的多线程

ExecutorService、Callable、Future 这个对象实际上都是属于 Executor 框架中的功能类。想要详细了解 Executor 框架的可以访问 http://www.javaeye.com/topic/366591 ,这里面对该框架做了很详细的解释。返回结果的线程是在 JDK1.5 中引入的新特征,确实很实用,有了这种特征我就不需要再为了得到返回值而大费周折了,而且即便实现了也可能漏洞百出。

可返回值的任务必须实现 Callable 接口,类似的,无返回值的任务必须 Runnable 接口。执行 Callable 任务后,可以获取一个 Future 的对象,在该对象上调用 get 就可以获取到 Callable 任务返回的 Object 了,再结合线程池接口 ExecutorService 就可以实现传说中有返回结果的多线程了。下面提供了一个完整的有返回结果的多线程测试例子,在 JDK1.5 下验证过没问题可以直接使用。代码如下:

import java.util.concurrent.*; 
import java.util.Date; 
import java.util.List; 
import java.util.ArrayList; 
  
/**
* 有返回值的线程
*/ 
@SuppressWarnings("unchecked") 
public class Test { 
public static void main(String[] args) throws ExecutionException, 
   InterruptedException { 
  System.out.println("----程序开始运行----"); 
  Date date1 = new Date(); 
  
  int taskSize = 5; 
  // 创建一个线程池 
  ExecutorService pool = Executors.newFixedThreadPool(taskSize); 
  // 创建多个有返回值的任务 
  List<Future> list = new ArrayList<Future>(); 
  for (int i = 0; i < taskSize; i++) { 
   Callable c = new MyCallable(i + " "); 
   // 执行任务并获取Future对象 
   Future f = pool.submit(c); 
   // System.out.println(">>>" + f.get().toString()); 
   list.add(f); 
  } 
  // 关闭线程池 
  pool.shutdown(); 
  
  // 获取所有并发任务的运行结果 
  for (Future f : list) { 
   // 从Future对象上获取任务的返回值,并输出到控制台 
   System.out.println(">>>" + f.get().toString()); 
  } 
  
  Date date2 = new Date(); 
  System.out.println("----程序结束运行----,程序运行时间【" 
    + (date2.getTime() - date1.getTime()) + "毫秒】"); 
} 
} 
  
class MyCallable implements Callable<Object> { 
private String taskNum; 
  
MyCallable(String taskNum) { 
  this.taskNum = taskNum; 
} 
  
public Object call() throws Exception { 
  System.out.println(">>>" + taskNum + "任务启动"); 
  Date dateTmp1 = new Date(); 
  Thread.sleep(1000); 
  Date dateTmp2 = new Date(); 
  long time = dateTmp2.getTime() - dateTmp1.getTime(); 
  System.out.println(">>>" + taskNum + "任务终止"); 
  return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】"; 
} 
}

代码说明:

上述代码中 Executors 类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了 ExecutorService 接口。

public static ExecutorService newFixedThreadPool (int nThreads) 创建固定数目线程的线程池。

public static ExecutorService newCachedThreadPool () 创建一个可缓存的线程池,调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。

public static ExecutorService newSingleThreadExecutor () 创建一个单线程化的 Executor。

public static ScheduledExecutorService newScheduledThreadPool (int corePoolSize) 创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代 Timer 类。

ExecutoreService 提供了 submit () 方法,传递一个 Callable,或 Runnable,返回 Future。如果 Executor 后台线程池还没有完成 Callable 的计算,这调用返回 Future 对象的 get () 方法,会阻塞直到计算完成。

IDEA 保姆级安装教程:  http://note.youdao.com/s/Wq2GSETJ  

计算机专业常用毕业设计集合:  http://note.youdao.com/s/PIJHOqnk  文章来源地址https://www.toymoban.com/news/detail-426497.html

到了这里,关于Java 多线程实现的三种方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 线程创建的三种方式

    线程创建的三种方式

    目录 1. Thread类 2. Runnable接口 3. Callable接口 4. 线程的生命周期 新建  就绪 运行 阻塞 等待 结束 继承Thread类的方式创建线程 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务 创建Thread类的子类,即创建了线程对象 调用线程对象的

    2024年02月09日
    浏览(9)
  • C++创建线程的三种方式

    早期的C++并不支持多线程的创建,如果要创建多线程,依赖的是系统提供的一些方法(例如linux的 pthread). 从C++11以后开始,提供了std::thread线程库,因此我们可以创建std::thread类对象的方式来创建线程。创建的方式主要有三种: 通过函数指针 通过函数对象 通过lambda函数 使用

    2024年02月16日
    浏览(9)
  • Springboot中使用线程池的三种方式

    前言 多线程是每个程序员的噩梦,用得好可以提升效率很爽,用得不好就是埋汰的火葬场。 这里不深入介绍,主要是讲解一些标准用法,熟读唐诗三百首,不会作诗也会吟。 这里就介绍一下springboot中的多线程的使用,使用线程连接池去异步执行业务方法。 由于代码中包含详

    2024年02月08日
    浏览(13)
  • Java 创建多线程的三种方法

    Java 创建多线程的三种方法

    在Java中创建多线程,往往都要通过Thread类来实现,今天学习下Java中创建多线程的三种方法[1]。 通过继承 Thread类 实现多线程。 主要方法: 1.void run(), 线程开启后,方法将被调用执行 2.void start(), 使此线程开始执行, Java虚拟机会调用run()方法 实现步骤: 1.定义类,继承 Thread类

    2024年02月05日
    浏览(8)
  • Java创建数组的三种方式

    这种一般用的比较多。 数组类型 [ ]  数组名称  =  new 数组类型 [ 数组长度 ] 

    2024年02月03日
    浏览(13)
  • Java创建文件的三种方式

    Java创建文件的三种方式

    内容来自于韩顺平学Java 在学习其视频下跟着编写 文件创建成功

    2024年04月11日
    浏览(16)
  • Java数组的三种声明方式

    1.在开发中为什么要使用数组 如果开发中出现了大量的同一个类型的数据,按照现在所学的知识点,声明变量的话。如果一个变量存一个数据的话,那么就会需要多个变量了,相当麻烦。 使用数组: 只需要一个变量,然后数组中存很多的数据, 其实可以把数组想成 一个容器

    2024年02月05日
    浏览(11)
  • Appium/Selenium+Java的三种等待方式

    参考: java-selenium三种等待方式 Selenium+Java(六)Selenium 强制等待、显式等待、隐实等待 强制等待是利用time模块的sleep方法来实现,最简单粗暴的等待方法。 缺点:不能准确把握需要等待的时间(有时候操作未完成,等待就结束了,导致报错;有时候操作已经完成了,但时间

    2024年02月05日
    浏览(6)
  • java对接第三方接口的三种方式

    在日常工作中,经常需要跟第三方系统对接,我们做为客户端,调用他们的接口进行业务处理,常用的几种调用方式有: 1.原生的Java.net.HttpURLConnection(jdk); 2.再次封装的HttpClient、CloseableHttpClient(Apache); 3.Spring提供的RestTemplate; 当然还有其他工具类进行封装的接口,比

    2024年04月28日
    浏览(10)
  • Docker 实现挂载的三种方式

    Docker 实现挂载的三种方式

    容器中运行的应用,有可能会产生数据,如果将数据直接存储到容器中,如果删除容器时,容器中的数据会一起被删除,例如: 如果运行的是数据库容器,数据库容器直接保存的数据文件,删除容器时,容易导致数据丢失 为了防止数据丢失,可以把数据保存到宿主机上,这样有便于容器之间

    2024年01月23日
    浏览(13)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包