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

时间:2010-01-20 09:23:45

标签: java multithreading

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

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

由于这段代码,我的提醒信息来得很晚。

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

我在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(),
            "vagarwal@q3tech.com", "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.";
    }
}

5 个答案:

答案 0 :(得分:14)

我不确定这是不是问题。发送电子邮件并不是那么昂贵的操作 - 它只是通知SMTP服务器应该发送邮件,而SMTP服务器会从那里开始处理。

不过,你可以试试:

new Thread(new Runnable() {
    public void run() {
        MailUtility.send(inviteeUser.getUserEmailAddress().trim(),
            "vagarwal@q3tech.com", "add friend message", Utility
                    .getAddFriendMessageBody(LoginHelper
                            .getLoggedInUserEmail()), false);
    }
}).start();

答案 1 :(得分:11)

我建议您在servlet中定义ExecutorService,然后向服务提交RunnableCallable,以便执行发送电子邮件的工作。

private ExecutorService execService = Executors.newFixedThreadPool(1);

...

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

这种方法的优点包括:

  • 您不会执行每次创建新Thread的昂贵操作。
  • 您可以更好地控制servlet中运行的#threads总数(因为电子邮件请求只是排队等待)。
  • 可以通过继承ThreadPoolExecutor并覆盖afterExecute(Runnable, Throwable)或定义CompletionService来检查每个已完成的Runnable的结果,从而集中处理错误。
  • 您的调用线程将传回一个Future,它可能会用于将结果编组回来或阻塞,直到异步计算完成。

答案 2 :(得分:5)

在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(),
               "vagarwal@q3tech.com", "add friend message", Utility
                    .getAddFriendMessageBody(LoginHelper
                            .getLoggedInUserEmail()), false);
         }
    });
}

PS。你可能需要让一些变量最终,以便它可以在runnable中使用,但我会把它作为读者的练习:)

答案 3 :(得分:1)

执行任务(在后台发送电子邮件)的另一个选择是让另一个小程序(可能是一个守护程序)定期读取数据库中的特殊表并发送电子邮件。程序可以用任何语言编写,并从OS后台进程开始。

这样做的好处是:

  1. 你可以使用你喜欢的hwatever编写这样一个守护进程。
  2. 您可以控制此守护程序的行为:检测两个人何时尝试互相添加给朋友。
  3. 性能 - 发送电子邮件可能会滥用服务器(尤其是网络接口)。拥有这样的守护进程,您可以将其安装在具有不同网络接口的不同服务器上。
  4. ....

答案 4 :(得分:0)

阅读

中的文档

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

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