我知道线程是软件/网络应用程序的关键成员。但我在大学项目中没有使用它们,该项目是关于使用 Java EE 技术进行在线购物的。
如果我将它们应用到我的项目中,有人可以告诉我它们如何有用吗?
我熟悉货币等,但只是想了解它们的重要性。例如,我为什么要费心将一些代码放在线程中(除了多个请求的事实,我应该费心)。只是有点困惑。
我知道线程是软件/网络应用程序的关键成员。但我在大学项目中没有使用它们,该项目是关于使用 Java EE 技术进行在线购物的。
如果我将它们应用到我的项目中,有人可以告诉我它们如何有用吗?
我熟悉货币等,但只是想了解它们的重要性。例如,我为什么要费心将一些代码放在线程中(除了多个请求的事实,我应该费心)。只是有点困惑。
如果您已经完成了一个 Java EE 项目,那么线程是您可能不会接触到的东西。使用 Java EE 时,您正在编写将插入某个容器的部件。例如,您编写 EJB 代码,应用程序服务器负责缓存这些并调用它们。您编写持久性实体,应用程序服务器将为您提供持久性上下文并处理事务......应用程序服务器将有许多线程池来处理客户端请求。它们都是为您管理的,因此您实际上看不到它。因为您正在针对框架进行编码。
切换到 Java SE,情况就不同了。如果您主要从头开始构建应用程序,可能使用一些库但不是真正的框架,那么在一个非平凡的应用程序中您可能需要多线程。虽然知道如何或何时以最佳方式使用并发是您通过学习和经验学到的东西(“Java 并发实践”一书是这里的首选),但您基本上可以说任何时候需要要在后台完成,同时还执行其他工作,或者您的程序可以继续而无需等待某些调用返回,多线程可以发挥作用。
由于您使用的是 Java EE,它已经是一个多线程环境,这就是您不需要多线程的原因。
您必须知道,对于到达您的 servlet 的每个请求,每个请求都由容器在单独的线程中处理。所以在后台你使用了容器提供的多线程。
我不知道现在我要给出的例子是否与任何实际情况有关,但这只是为了理解:
说新年,您需要向所有注册用户发送一封电子邮件,告知您购物网站上的新年优惠。因此,您的数据库中可能有数千甚至更多的客户。所以你可以在这里使用线程来执行发送电子邮件的任务,比如为 1000 个客户,你可以使用 10 个线程,每个线程向 100 个客户发送电子邮件。注意:这只是我想到的一个场景。
这真的取决于上下文。如果您正在编写 Java,那么您很可能在服务器上。如果是这样,您的应用程序服务器通常会管理线程。
如今,客户端 Java 代码很少见,但仍然存在。例如,Swing 中的线程对于后台任务很重要,因此不会阻塞重绘/事件线程。
理解线程安全的概念可能比“何时使用线程”更重要。Joshua Bloch 的 Effective Java 是一本很棒的书(或者很多年前我读到它时)。
(请记住,这与您选择使用的任何平台套件无关。)
想象一下,如果你愿意,你要去购物,而你的篮子里没有很多东西。大约有十个人在你面前购物,他们中的许多人的篮子里还有很多东西。与打开另一条通道相比,当您几乎没有结帐通道必须处理的那么多东西时,处理您需要更长的时间。
线程类似于商店中的结帐通道。您拥有的它们越多,您可以执行的操作就越多。
随着计算机不再变得越来越快,并且更加专注于在芯片上放置更多内核,我们作为软件工程师必须想出方法来提高我们的算法和应用程序的效率,以适应我们硬件的使用。多线程是一种方式。我们可以设计和实现算法来处理一个大问题并将其划分为更小的子问题,以便稍后重新组合。
线程有一个开销,这是在轻量级进程的上下文切换和启动中。如果您只有一个核心,您将花费更多时间来处理开销,而不是处理任何实际数据。
我已经分享了我对结帐通道的类比,虽然打开更多通道通常是好的,但如果没有足够的工作让所有通道都打开它们是合理的,那么它们就是浪费资源和时钟周期。平衡您必须做的工作量与您需要的线程数是至关重要的。
我曾经有一个系统接收到一个请求(只是一个 HTTP 帖子)来处理数据列表。对于每一位数据,它需要调用另一个系统并等待 1-6 秒的响应。处理 1000 位数据需要数十分钟。HTTP 连接将超时。所以我使用并发向远程系统一次发出 20 或 30 个请求。无论如何,我的系统大多只是在等待。这将总处理时间减少到以前的 3% 到 5%,每个人都很高兴。
现在,请注意,在 Java EE 容器中使用 Java SE 并发特性是不合法的。容器正在执行各种多线程,您的多线程会或可能会干扰。我们发现尽管我们违反了规则,但我们正在做的事情还不错。在其他情况下,我尝试过它并发现它不起作用。
如果您使用 WebSphere 或 Weblogic Java EE 容器,它们都具有处理多线程的专有框架。它是同一个标准,并且是一个提议的标准,但今天我不知道这个名字。
如果您使用的是 Tomcat 之类的 servlet 容器,则可以使用 Java SE 多线程。
Spring 框架有一些实用程序类,您可以对其进行编程以满足某些并发需求。这些使得将支持并发从 Java SE 切换到 IBM 和 Oracle 使用的框架变得容易。