Javaスレッドプログラミング(その2 )

5376 ワード

この記事は2007年に初めて発表されましたFoojay.io
インour earlier article , スレッドを作成してスレッドを開始する方法を説明します.
この記事では、我々の利点に糸を使用できる例を見てみましょう.
Webサーバを構築しようとしましょう.例のために、ウェブサーバーがどんなクライアントにも聞くということである1つの一つのユースケースに専念しましょう、そして、それがURLを受けるならば、それはそのウェブサイトでトップ5の最も頻繁に使われる語を返します.
OK、十分な話、コードを見ましょう!
package com.bazlur;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.stream.Collectors;

public class SingleThreadedServer {
  private final MostFrequentWordService mostFrequentWordService = new MostFrequentWordService();

  public SingleThreadedServer(int port) throws IOException {
    var serverSocket = new ServerSocket(port);
    while (true) {
      var socket = serverSocket.accept();
      handle(socket);
    }
  }

  private void handle(Socket socket) {
    System.out.println("Client connected: " + socket);

    try (var in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
         var out = new PrintWriter(socket.getOutputStream(), true)) {
      String line;

      while ((line = in.readLine()) != null) {
        if (isValid(line)) {
          var wordCount = mostFrequentWordService.mostFrequentWord(line)
                  .stream()
                  .map(counter -> counter.word() + ": " + counter.count())
                  .collect(Collectors.joining("\n"));
          out.println(wordCount);
        } else if (line.contains("quit")) {
          out.println("Goodbye!");
          socket.close();
        } else {
          out.println("Malformed URL");
        }
      }
    } catch (IOException e) {
      System.out.println("Was unable to establish or communicate with client socket:" + e.getMessage());
    }
  }

  private static boolean isValid(String stringURL) {
    try {
      new URL(stringURL);
    } catch (MalformedURLException e) {
      System.out.println("invalid url: " + stringURL);
      return false;
    }
    return true;
  }

  public static void main(String[] args) throws IOException {
    new SingleThreadedServer(2222);
  }
}

まずコードを歩きましょう.上のコードでServerSocket ポートで起動し、クライアントが接続するループで待機します.The handle() メソッドは最も重要なものです.ソケットオブジェクトを取得し、クライアントに話をします.クライアントが有効なURLを送るなら、それはサービスを呼びます.MostFrequentWordService , 最も頻繁に単語を取得します.
telnetを使ってサーバを接続し、このサーバを使うことができます.

これに関する唯一の問題は一度に1つのクライアントだけを扱うことができます.したがって、他のクライアントを接続しようとすると、他の接続されたクライアントが切断された場合にのみ応答します.
それは確かにWebサーバーの問題です.Webサーバは、何百または数千のクライアントと同時に接続することになっています.
このシングルスレッドプログラムをマルチスレッドプログラムにすると、この問題をすぐに解決できます.回収するhandle() 上記コードからのメソッド.クライアントが接続するたびに、新しいスレッドを生成し、handle() スレッドへのメソッド
はい、それはトリックです.しましょう
public class MultiThreadedServer {
  private final MostFrequentWordService mostFrequentWordService = new MostFrequentWordService();

  public MultiThreadedServer(int port) throws IOException {
    var serverSocket = new ServerSocket(port);
    while (true) {
      var socket = serverSocket.accept();

      var thread = new Thread(() -> handle(socket));
      thread.start();
    }
  }

  //rest of the code. 
}

さて、複数のクライアントを一度に接続することができます.

Javaでスレッドを使用する利点を理解しているので、このシリーズでは次の記事のスレッドを使用してスレッドを深く掘ります.
そして、あなたが私が「mostExcepdWordService」を書いた方法に興味があるならば、ここにあります:
package com.bazlur;

import org.jsoup.Jsoup;

import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

record WordCount(String word, long count) {
}

public class MostFrequentWordService {
  public List mostFrequentWord(String url) throws IOException {
    var wordCount = Arrays.stream(getWords(url))
            .filter(value -> !value.isEmpty())
            .filter(value -> value.length() > 3)
            .map(String::toLowerCase)
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

    return wordCount.entrySet()
            .stream()
            .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
            .limit(5)
            .map(entry -> new WordCount(entry.getKey(), entry.getValue()))
            .collect(Collectors.toList());
  }

  private String[] getWords(String url) throws IOException {
    var connect = Jsoup.connect(url);
    var document = connect.get();
    var content = document.body().text();

    return content.split("[^a-zA-Z]");
  }
}

今日はこれだ!
このポストを共有することを忘れないでください!