2010-01-20 22 views
9

Tôi đang viết một ứng dụng mà người dùng có thể thêm và xóa người dùng khác làm bạn bè. Trang của tôi có danh sách những người dùng khác nhau và mỗi người dùng được cung cấp một nút để thêm họ vào danh sách bạn bè. Tôi đang gửi một yêu cầu AJAX tới Java servlet để thêm người dùng đã chọn làm bạn. Tôi đang hiển thị thông báo cảnh báo tại giao diện người dùng để hiển thị kết quả của quá trình.Chạy quá trình nền trong các chủ đề khác nhau trong Java

Vấn đề của tôi là tôi phải gửi thư khi người dùng được thêm làm bạn bè, mã này được viết bằng cùng một phương thức trong servlet.

Vì đoạn mã này, thông báo cảnh báo của tôi đến trễ.

Tôi cần chạy một pthread riêng để chạy chức năng gửi thư này để khi người dùng được thêm tôi sẽ nhận được kết quả và thư sẽ được gửi trong quá trình riêng biệt.

Mã của tôi trong Servlet là

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."; 
    } 
} 

Trả lời

0

Đọc tài liệu ở

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

Bạn nên phân lớp java.lang.Thread thực hiện phương pháp chạy của bạn. Nó có thể sẽ giống như sendMail hiện tại của bạn. Sau đó, bạn gọi phương thức bắt đầu trên chuỗi và kiểm soát trả về ngay lập tức cho dòng mã tiếp theo trong khi luồng được thực thi ở chế độ nền.

+2

Cách ưu tiên sẽ là xác định một lớp thực hiện Runnable và sau đó tạo chủ đề truyền trong thể hiện Runnable. Sub-classing Thread là một hình thức kế thừa thực hiện và thường không được khuyến khích. – Adamski

14

Tôi không chắc đây là vấn đề. Gửi một email không hoàn toàn là hoạt động tốn kém - nó chỉ thông báo cho máy chủ SMTP rằng thư sẽ được gửi và máy chủ SMTP sẽ xử lý từ đó.

Tuy nhiên, bạn có thể thử:

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

Đối với tôi gửi email là hoạt động tốn kém – gstackoverflow

11

tôi khuyên bạn nên xác định một ExecutorService trong servlet của bạn rồi gửi Runnable hoặc Callable đến dịch vụ để thực hiện công việc gửi email.

private ExecutorService execService = Executors.newFixedThreadPool(1); 

... 

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

Ưu điểm của phương pháp này bao gồm:

  • Bạn không thực hiện các hoạt động tốn kém của việc tạo ra một mới Thread mỗi lần.
  • Bạn giữ quyền kiểm soát tốt hơn tổng số #thread đang chạy trong servlet của bạn (vì các yêu cầu email được xếp hàng đợi đơn giản).
  • Xử lý lỗi có thể được tập trung, hoặc bằng cách phân lớp ThreadPoolExecutor và ghi đè afterExecute(Runnable, Throwable) hoặc bằng cách xác định CompletionService để kiểm tra kết quả của từng hoàn thành Runnable.
  • Chuỗi cuộc gọi của bạn được truyền lại trong tương lai, có thể được sử dụng để kết hợp lại kết quả hoặc chặn cho đến khi tính toán không đồng bộ đã hoàn thành.
5

khá đơn giản trong java 5 trở lên:

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.bạn có thể cần phải thực hiện một số biến cuối cùng để nó có thể sử dụng được bên trong runnable, nhưng tôi sẽ để nó như một bài tập cho người đọc :)

1

Một tùy chọn khác để thực hiện tác vụ của bạn (để gửi email trong nền) là để có một chương trình nhỏ khác (có thể là một daemon) sẽ định kỳ đọc Bảng đặc biệt trong DB và gửi email. Chương trình có thể được viết bằng bất kỳ ngôn ngữ nào và bắt đầu trong quá trình xử lý nền hệ điều hành.

Dưới đây là những ưu điểm của làm theo cách đó:

  1. Bạn có thể sử dụng hwatever bạn muốn viết một daemon như vậy.
  2. Bạn có thể kiểm soát hành vi của daemon như vậy: để phát hiện khi hai người cố gắng thêm lẫn nhau cho bạn bè.
  3. Hoàn hảo - việc gửi email có thể lạm dụng máy chủ (đặc biệt là giao diện mạng). Có một daemon như vậy bạn có thể cài đặt nó trên máy chủ defferent với giao diện mạng khác nhau.
  4. ....
Các vấn đề liên quan