用java编写多线程代码的4种方法

在本文中,我们比较了几种用Java编写多线程代码的选项,这样您就可以更好地判断下一个Java项目使用哪种选项。...

多线程是一种编写代码以并行执行任务的方法。从Java1.0的早期开始,Java就对编写多线程代码提供了极好的支持。最近对Java的增强增加了在Java程序中构建多线程代码的方式。

multi-threaded-code-java

在本文中,我们比较了其中的几个选项,以便您可以更好地判断下一个Java项目使用哪个选项。

Multiple worker threads within a process.

方法1:扩展线程类

Java提供了一个线程类,可以扩展该类来实现run()方法。这个run()方法是实现任务的地方。当您想在自己的线程中启动任务时,可以创建此类的实例并调用其start()方法。这将启动线程执行并运行到完成(或在异常中终止)。

Extending Thread allows a worker task to run in a separate thread

下面是一个简单的Thread类,它只在指定的时间间隔内休眠,以此来模拟长时间运行的操作。

public class MyThread extends Thread{ private int sleepFor; public MyThread(int sleepFor) { this.sleepFor = sleepFor; } @Override public void run() { System.out.printf("[%s] thread starting", Thread.currentThread().toString()); try { Thread.sleep(this.sleepFor); } catch(InterruptedException ex) {} System.out.printf("[%s] thread ending", Thread.currentThread().toString()); }}

通过给线程类提供睡眠的毫秒数来创建该线程类的实例。

MyThread worker = new MyThread(sleepFor);

通过调用它的start()方法启动这个工作线程的执行。此方法立即将控制权返回给调用方,而不等待线程终止。

worker.start();System.out.printf("[%s] main thread", Thread.currentThread().toString());

下面是运行这个代码的输出。它指示在工作线程执行之前打印主线程诊断。

[Thread[main,5,main]] main thread[Thread[Thread-0,5,main]] thread starting[Thread[Thread-0,5,main]] thread ending

因为在启动工作线程之后没有更多的语句,所以主线程在程序退出之前等待工作线程完成。这允许工作线程完成其任务。

方法2:使用具有runnable的线程实例

Java还提供了一个名为Runnable的接口,它可以由一个worker类实现,以在其run()方法中执行任务。这是创建worker类的另一种方法,而不是扩展Thread类(如上所述)。

Class Papaya extends Fruit but implements Runnable to be able to run a task in a separate thread.

下面是worker类的实现,它现在实现Runnable而不是扩展Thread。

public class MyThread2 implements Runnable { // same as above}

实现Runnable接口而不是扩展Thread类的优点是,worker类现在可以在类层次结构中扩展特定于域的类。

这是什么意思?

例如,我们假设您有一个水果类,它实现水果的某些泛型特征。现在您要实现一个专门处理某些水果特性的木瓜类。你可以通过让木瓜类扩展水果类来做到这一点。

public class Fruit { // fruit specifics here}public class Papaya extends Fruit { // override behavior specific to papaya here}

现在假设您有一些Papaya需要支持的耗时任务,可以在单独的线程中执行。这种情况可以通过让Papaya类实现Runnable并提供执行此任务的run()方法来处理。

public class Papaya extends Fruit implements Runnable { // override behavior specific to papaya here @Override public void run() { // time c***uming task here. }}

要启动工作线程,需要创建工作类的实例,并在创建时将其交给线程实例。当线程的start()方法被调用时,任务在一个单独的线程中执行。

Papaya papaya = new Papaya();// set properties and invoke papaya methods here.Thread thread = new Thread(papaya);thread.start();

这是如何使用Runnable来实现在线程中执行的任务的简要总结。

方法3:使用executorservice执行runnable

An ExecutorService provides an abstraction for creating and managing threads.

从版本1.5开始,Java提供了ExecutorService,作为在程序中创建和管理线程的新范例。它通过抽象线程的创建来概括线程执行的概念。

这是因为您可以在线程池中运行任务,就像为每个任务使用单独的线程一样简单。这允许您的程序跟踪和管理有多少线程用于辅助任务。

假设有100个辅助任务等待执行。如果您为每个worker启动一个线程(如上所示),那么您的程序中将有100个线程,这可能会导致程序中其他地方出现瓶颈。相反,如果使用预先分配了10个线程的线程池,那么100个任务将由这些线程一个接一个地执行,这样程序就不会缺少资源。此外,可以配置这些线程池线程,以便它们挂起为您执行其他任务。

ExecutorService接受可运行的任务(如上所述),并在适当的时间运行该任务。接受可运行任务的submit()方法返回一个名为Future的类的实例,该类允许调用方跟踪任务的状态。特别是,get()方法允许调用方等待任务完成(并提供返回代码,如果有的话)。

在下面的示例中,我们使用静态方法newSingleThreadExecutor()创建一个ExecutorService,正如名称所示,它创建一个用于执行任务的线程。如果在一个任务运行时提交了多个任务,ExecutorService会将这些任务排队等待后续执行。

我们在这里使用的可运行实现与上面描述的相同。

ExecutorService esvc = Executors.newSingleThreadExecutor();Runnable worker = new MyThread2(sleepFor);Future<?> future = esvc.submit(worker);System.out.printf("[%s] main thread", Thread.currentThread().toString());future.get();esvc.shutdown();

请注意,当不再需要进一步提交任务时,必须正确关闭ExecutorService。

方法4:与executorservice一起使用的可调用

从版本1.5开始,Java引入了一个名为Callable的新接口。它类似于旧的Runnable接口,不同之处在于执行方法(调用call()而不是run())可以返回一个值。此外,它还可以声明可以抛出异常。

ExecutorService还可以接受实现为可调用的任务,并使用方法在完成时返回的值返回Future。

下面是一个示例Mango类,它扩展了前面定义的Fruit类并实现了可调用接口。在call()方法中执行一项昂贵且耗时的任务。

An implementation of the Callable interface can also be used with an ExecutorService

public class Mango extends Fruit implements Callable { public Integer call() { // expensive computation here return new Integer(0); }}

下面是将类的实例提交给ExecutorService的代码。下面的代码还将等待任务完成并打印其返回值。

ExecutorService esvc = Executors.newSingleThreadExecutor();MyCallable worker = new MyCallable(sleepFor);Future future = esvc.submit(worker);System.out.printf("[%s] main thread", Thread.currentThread().toString());System.out.println("Task returned: " + future.get());esvc.shutdown();

你喜欢什么?

在本文中,我们学习了一些用Java编写多线程代码的方法。其中包括:

  1. 扩展Thread类是最基本的,Java1.0提供了它。
  2. 如果有一个类必须扩展类层次结构中的其他类,那么可以实现Runnable接口。
  3. 创建线程的一个更现代的工具是ExecutorService,它可以接受一个可运行实例作为要运行的任务。此方法的优点是可以使用线程池执行任务。线程池通过重用线程来帮助节约资源。
  4. 最后,还可以通过实现可调用接口并将任务提交给ExecutorService来创建任务。

你认为在你的下一个项目中你会使用这些选项中的哪一个?请在下面的评论中告诉我们。

  • 发表于 2021-03-14 04:48
  • 阅读 ( 176 )
  • 分类:编程

你可能感兴趣的文章

睡觉(sleep)和在java中等待(wait in java)的区别

...关键区别——java中的休眠与等待 Sleep和wait是Java中用于多线程处理的两种方法。sleep方法属于Thread类,而wait方法来自Object类。Java中sleep和wait的关键区别在于,sleep用于在指定的毫秒数内暂停当前线程的执行,而wait方法用于使当...

  • 发布于 2020-10-19 03:04
  • 阅读 ( 270 )

源代码(source code)和字节码(bytecode)的区别

...程序可以向计算机发出指令。它是用一套特定的编程语言编写的。编程语言有很多种。大多数编程语言都是高级编程语言。用高级语言编写的程序很容易被人或程序员理解。这些程序称为源代码。机器无法理解它们。因此,人类...

  • 发布于 2020-10-19 15:49
  • 阅读 ( 633 )

可运行(runnable)和线(thread)的区别

...o实现了Runnable接口。使用线程执行的逻辑是用run()方法编写的。在主程序中,线程是通过定义一个从可运行的Demo类实例化的对象来创建的。是t1。然后,使用t1调用start()方法。 什么是线(thread)? 另一种创建线程的方法是扩...

  • 发布于 2020-10-19 19:23
  • 阅读 ( 185 )

初学者必备的8个eclipse键盘快捷键

本文最初是为eclipsejuno编写的,但后来为eclipseoxygen进行了更新。 ...

  • 发布于 2021-03-11 23:36
  • 阅读 ( 334 )

java8lambdas简介

... 使用lambda,可以将上述循环编写为: ...

  • 发布于 2021-03-12 08:09
  • 阅读 ( 240 )

为什么java虚拟机可以帮助代码更好地运行

... 本机应用程序是专门为操作系统(OS)编写的程序,也可能是为运行该操作系统的特定硬件编写的程序。它主要是用C/C++等语言编写的。C/C++源代码使用编译器编译成对象形式,然后通过链接所需的库将其组装...

  • 发布于 2021-03-13 07:13
  • 阅读 ( 242 )

microsoft.net framework:为什么需要它以及如何在windows上安装它

...。为此,您需要一点编程上下文——但如果您一生中从未编写过任何代码,请不要担心!这个解释将假设你完全没有编程经验。 ...

  • 发布于 2021-03-17 04:56
  • 阅读 ( 309 )

如何用java编写for循环

...内容。要打印数组的内容,必须打印数组中的每个元素。编写代码会很费时,但您可以创建一个for循环来遍历每个元素。 ...

  • 发布于 2021-03-29 11:52
  • 阅读 ( 229 )

谷歌首席java架构师:很可能是我复制了android中的sun代码,如果是的话,我很抱歉

...的数字数组是否在特定的定义范围内。布洛赫作证说,他编写了原始的rangeCheck代码,存在于一个名为数组.java,早在1997年。在法庭文件中,Sun声称rangeCheck代码的版权日期为2004年。 在一个名为Timsort.java布洛赫在2007年...

  • 发布于 2021-04-22 02:17
  • 阅读 ( 171 )

面向初学者的五种最佳编程语言

...确一点,我们并不是要绝对解决一个问题,即如果你试图编写代码,你应该先学习哪种语言。每个人都有不同的观点,这取决于你学习的具体原因,也许这些都不合适。你提供了更多的建议,在我们的呼吁竞争者线程比我们可能...

  • 发布于 2021-05-22 04:29
  • 阅读 ( 187 )
lts9441
lts9441

0 篇文章

相关推荐