java 在Java中的不同线程中运行后台进程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2100212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 19:26:35  来源:igfitidea点击:

Run background process in different thread in Java

javamultithreading

提问by viredra-agarwal

I am writing an application where user can add and remove other users as friends. My page has a list of diffrent users and each user is given with a button to add them in friend list. I am sending a AJAX request to Java servlet to add the selected user as a friend. I am showing alert message at UI to show the result of process.

我正在编写一个应用程序,用户可以在其中添加和删除其他用户作为朋友。我的页面有一个不同用户的列表,每个用户都有一个按钮,可以将他们添加到朋友列表中。我正在向 Java servlet 发送 AJAX 请求以将所选用户添加为朋友。我在 UI 上显示警报消息以显示处理结果。

My problem is i have to sent a mail when user is added as friend this code is written in the same method in the servlet.

我的问题是,当用户被添加为朋友时,我必须发送一封邮件,此代码在 servlet 中以相同的方法编写。

Because of this piece of code my alert message comes very late.

由于这段代码,我的警报消息来得很晚。

I need to run a separate pthread to run this send mail function so that once user is added i will get the result and mail will be send in separate process.

我需要运行一个单独的 pthread 来运行这个发送邮件功能,这样一旦添加用户,我就会得到结果,邮件将在单独的进程中发送。

My code in the Servlet is

我在 Servlet 中的代码是

private void sendMail(long inviteeID) {
    User inviteeUser = null;
    try {
        inviteeUser = userHandler.getUser(inviteeID);
    } catch (DataException e) {
        sLog.error("User does not exist.", e);
    } catch (UserNotFoundException e) {
        sLog.error("User does not exist.", e);
    }
    MailUtility.send(inviteeUser.getUserEmailAddress().trim(),
            "[email protected]", "add friend message", Utility
                    .getAddFriendMessageBody(LoginHelper
                            .getLoggedInUserEmail()), false);
}



private String inviteAsFriend(long inviteeID) {

    boolean result = false;

    if (LoginHelper.isUserLoggedIn()) {
        try {
            User user = userHandler.findUserByEmail(LoginHelper
                    .getLoggedInUserEmail());

            if (userHandler.isUserFriend(user.getUserId(), inviteeID)) {

                if (userHandler.addFriend(user, inviteeID)) {

                    result = true;
                    return "Member added successfully as your friend.";
                } else {

                    return "Member could not be added as your friend. Please try again later.";
                }

            } else {

                return "Member is already your friend.";
            }

        } catch (DataException e) {

            return "User does not exist.";
        } catch (UserNotFoundException e) {

            return "User does not exist.";
        } catch (Exception e) {

            return "Member could not be added as your friend. Please try again later.";
        } finally {
            if (result) {
                sendMail(inviteeID);
            }
        }
    } else {
        return "User not logged in.";
    }
}

回答by Bozho

I'm not sure this is the problem. Sending an email is not quite that expensive operation - it just informs the SMTP server that the mail should be sent, and the SMTP server takes care from there on.

我不确定这是问题所在。发送电子邮件并不是那么昂贵的操作——它只是通知 SMTP 服务器应该发送邮件,然后 SMTP 服务器会负责处理。

Still, you could try:

不过,您可以尝试:

new Thread(new Runnable() {
    public void run() {
        MailUtility.send(inviteeUser.getUserEmailAddress().trim(),
            "[email protected]", "add friend message", Utility
                    .getAddFriendMessageBody(LoginHelper
                            .getLoggedInUserEmail()), false);
    }
}).start();

回答by Adamski

I'd suggest defining an ExecutorServicewithin your servlet and then submit a Runnableor Callableto the service in order to perform the work of sending the email.

我建议ExecutorService在您的 servlet 中定义一个,然后将一个Runnableor提交Callable给服务以执行发送电子邮件的工作。

private ExecutorService execService = Executors.newFixedThreadPool(1);

...

execService.submit(new Runnable()) {
  public void run() {
    // Send email.
  }
};

Advantages of this approach include:

这种方法的优点包括:

  • You do not perform the expensive operation of creating a new Threadeach time.
  • You retain greater control over the total #threads running in your servlet (as email requests are simply queued up).
  • Error handling can be centralised, either by subclassing ThreadPoolExecutorand overriding afterExecute(Runnable, Throwable)or by defining a CompletionServiceto inspect the results of each completed Runnable.
  • Your calling thread is passed back a Future, which can potentially be used to marshall the results back or block until the asynchronous computation has completed.
  • 您不必Thread每次都执行昂贵的创建新操作。
  • 您可以更好地控制在 servlet 中运行的总 #threads(因为电子邮件请求只是排队)。
  • 错误处理可以集中,通过子类化ThreadPoolExecutor和覆盖afterExecute(Runnable, Throwable)或通过定义 aCompletionService来检查每个完成的结果Runnable
  • 您的调用线程被传回一个 Future,它可能用于将结果编组或阻塞,直到异步计算完成。

回答by Chii

fairly simple in java 5 or above:

在 java 5 或更高版本中相当简单:

private final ExecutorService executor = Executors.newFixedThreadPool(MAX_ALLOWED_THREADS);
private void sendMail(long inviteeID) {
    User inviteeUser = null;
    try {
        inviteeUser = userHandler.getUser(inviteeID);
    } catch (DataException e) {
        sLog.error("User does not exist.", e);
    } catch (UserNotFoundException e) {
        sLog.error("User does not exist.", e);
    }
    executor.submit(new Runnable() {
         public void run() {
            MailUtility.send(inviteeUser.getUserEmailAddress().trim(),
               "[email protected]", "add friend message", Utility
                    .getAddFriendMessageBody(LoginHelper
                            .getLoggedInUserEmail()), false);
         }
    });
}

ps. you may need to make some variables final in order for it to be usable inside the runnable, but i ll leave that as an exercise for the reader :)

附:您可能需要将一些变量设为 final 才能使其在 runnable 中可用,但我将其留给读者作为练习:)

回答by ponkin

Another option to do your task(to send email in background) is to have another small program(may be a daemon) which will periodically read the special Table in DB and send email. Program may be writen in any language and starting in OS background proccess.

完成您的任务(在后台发送电子邮件)的另一种选择是使用另一个小程序(可能是守护进程),它会定期读取数据库中的特殊表并发送电子邮件。程序可以用任何语言编写并在操作系统后台进程中启动。

Here is the advantages of doing that way:

这是这样做的优点:

  1. You may use hwatever you like to write such a daemon.
  2. You can control the behaivor of such daemon: to detect when two people trying to add each other to friends.
  3. Perfomance - sending emails may abuse server(especially network interface). Having such a daemon you can install it on defferent server with different network interface.
  4. ....
  1. 你可以使用你喜欢的 hwatever 来编写这样的守护进程。
  2. 您可以控制此类守护程序的行为:检测两个人何时试图将对方添加为朋友。
  3. 性能 - 发送电子邮件可能会滥用服务器(尤其是网络接口)。拥有这样的守护进程,您可以将其安装在具有不同网络接口的不同服务器上。
  4. ....

回答by silviot

Read the documentation at

阅读文档

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html

You should subclass java.lang.Thread implementing your run method. It will probably be like your current sendMail. Then you call the method start on the thread, and control returns immediately to the next line of code while the thread is executed in background.

您应该子类化 java.lang.Thread 实现您的 run 方法。它可能就像您当前的 sendMail。然后在线程上调用方法 start,当线程在后台执行时,控制立即返回到下一行代码。