суббота, 11 июля 2020 г.

Потокобезопасность. Начало.

Мое знакомство с многопоточностью.

Плохой пример:
public class PingServlet extends HttpServlet {
    private List OutputList = new ArrayList<>();
    private List OutputErrorList = new ArrayList<>();
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        OutputList.clear();
        OutputErrorList.clear();
        try {
            String ip = request.getParameter("ip");
            InetAddress host = InetAddress.getByName(ip);
            int ping_count = 4;
            int ping_timeout_seconds = 2;
            int ping_timeout_milliseconds = ping_timeout_seconds * 1000;
            int ping_ttl = 54;
            OutputList.add("Обмен " + ping_count + " пакетами с timeout " + ping_timeout_seconds + " сек. и TTL " + ping_ttl + ".");
            int i = 1;
            while (i <= ping_count) {                 if (host.isReachable(null, ping_ttl, ping_timeout_milliseconds)) {                     OutputList.add(ip + ": ОК.");                 } else {                     OutputList.add(ip + ": узел недоступен.");                 }                 i++;             }         } catch (Exception e) {             e.printStackTrace();             OutputErrorList.add(e.toString());         }         response.setContentType("text/html; charset=UTF-8"); // Для правильной обработки кириллицы.         if (request.getCharacterEncoding() == null) { // Без этого неправильно выполнялась обработка ввода с кирилицей.             request.setCharacterEncoding("UTF-8");         }         request.getSession().setAttribute("servlet_data_ping", OutputList);         request.getSession().setAttribute("servlet_error_ping", OutputErrorList);         request.getRequestDispatcher("ping.jsp").include(request, response);     } }

Внимание на эти строки:



При такой реализации одновременное выполнение в нескольких потоках приводит к смешиванию значений из нескольких потоков в одной переменной:


Один из вариантов исправления:
public class PingServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List OutputList = new ArrayList<>();
        List OutputErrorList = new ArrayList<>();
        try {
            String ip = request.getParameter("ip");
            InetAddress host = InetAddress.getByName(ip);
            int ping_count = 4;
            int ping_timeout_seconds = 2;
            int ping_timeout_milliseconds = ping_timeout_seconds * 1000;
            int ping_ttl = 54;
            OutputList.add("Обмен " + ping_count + " пакетами с timeout " + ping_timeout_seconds + " сек. и TTL " + ping_ttl + ".");
            int i = 1;
            while (i <= ping_count) {                 if (host.isReachable(null, ping_ttl, ping_timeout_milliseconds)) {                     OutputList.add(ip + ": ОК.");                 } else {                     OutputList.add(ip + ": узел недоступен.");                 }                 i++;             }         } catch (Exception e) {             e.printStackTrace();             OutputErrorList.add(e.toString());         }         response.setContentType("text/html; charset=UTF-8"); // Для правильной обработки кириллицы.         if (request.getCharacterEncoding() == null) { // Без этого неправильно выполнялась обработка ввода с кирилицей.             request.setCharacterEncoding("UTF-8");         }         request.getSession().setAttribute("servlet_data_ping", OutputList);         request.getSession().setAttribute("servlet_error_ping", OutputErrorList);         request.getRequestDispatcher("ping.jsp").include(request, response);     }     protected void doPost(HttpServletRequest request, HttpServletResponse response) {     } }


Внимание на эти строки:

Комментариев нет:

Архив