2017-02-03 1 views
1

Ich habe diesen Code, um herauszufinden, wie von einer URL den Statuscode zu erhalten:Wie Datei als Eingabe geben und in mehreren Threads arbeiten?

import java.io.IOException; 
import java.net.HttpURLConnection; 
import java.net.URL; 

/** 
* @author Crunchify.com 
* 
*/ 

class j { 
    public static void main(String args[]) throws Exception { 

     String[] hostList = { "http://example.com", "http://example2.com","http://example3.com" }; 

     for (int i = 0; i < hostList.length; i++) { 

      String url = hostList[i]; 
      String status = getStatus(url); 

      System.out.println(url + "\t\tStatus:" + status); 
     } 
    } 

    public static String getStatus(String url) throws IOException { 

     String result = ""; 
     try { 
      URL siteURL = new URL(url); 
      HttpURLConnection connection = (HttpURLConnection) siteURL 
        .openConnection(); 
      connection.setRequestMethod("HEAD"); 
      connection.connect(); 

      int code = connection.getResponseCode(); 

       result = Integer.toString(code); 

     } catch (Exception e) { 
      result = "->Red<-"; 
     } 
     return result; 
    } 
} 

ich es für kleine Eingabe überprüft haben, es funktioniert gut. Aber ich habe Millionen von Domänen, die ich scannen muss. Ich habe eine Datei, die es enthält.

  1. Ich möchte wissen, wie ich Datei als Eingabe für diesen Code geben kann.
  2. Ich möchte den Code in mehreren Threads arbeiten. Sagen Sie, die Anzahl der Threads sollte mehr als 20000 betragen, damit meine Ausgabe schneller wird.
  3. Wie kann ich das in eine andere Datei schreiben?

Bitte helfen Sie mir. Wenn möglich würde ich gerne wissen, welche Bandwidth Savvy-Methode die gleiche Aufgabe erfüllt. Ich möchte den Code sowieso schneller machen. Wie kann ich diese Sache mit dem Code, den ich habe, machen? Java Version:

java version "1.8.0_121" 
Java(TM) SE Runtime Environment (build 1.8.0_121-b13) 
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode) 
+0

Sie könnten die Datei in eine Liste einlesen, Unterlisten erstellen und Threads erstellen, die jeweils an einer solchen Unterliste arbeiten. – Tim

+1

Ich würde sagen, wenn Ihre Thread-Anzahl ist "20000" Sie werden feststellen, dass es langsam als eine Kugel in Klebstoff ist. – Kayaman

+0

@Tim Können Sie mir bitte zeigen, wie das möglich ist. Ich bin in diesem Fall neu in Multi Thread. Weil ich mehr als 20000 Threads zur Zeit verwenden muss. Mein Code ist momentan nicht schneller. –

Antwort

1

Das tut, was Sie wollen:

Eingangslistendatei (c: //lines.txt)

http://www.adam-bien.com/ 
http://stackoverflow.com/ 
http://www.dfgdfgdfgdfgdfgertwsgdfhdfhsru.de 
http://www.google.de 

Das Thema:

import java.net.HttpURLConnection; 
import java.net.URL; 
import java.util.concurrent.Callable; 

public class StatusThread implements Callable<String> { 

    String url; 

    public StatusThread(String url) { 
     this.url = url; 
    } 

    @Override 
    public String call() throws Exception { 

     String result = ""; 
     try { 
      URL siteURL = new URL(url); 
      HttpURLConnection connection = (HttpURLConnection) siteURL.openConnection(); 
      connection.setRequestMethod("HEAD"); 
      connection.connect(); 

      int code = connection.getResponseCode(); 

      result = Integer.toString(code); 

     } catch (Exception e) { 
      result = "->Red<-"; 
     } 
     return url + "|" + result; 
    } 
} 

Und das Hauptprogramm :

import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Paths; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.stream.Stream; 

public class CallableExample { 
    public static void main(String[] args) throws IOException { 

     // Number of threads 
     int numberOfThreads = 10; 

     // Input file 
     String sourceFileName = "c://lines.txt"; // Replace by your own 
     String targetFileName = "c://output.txt"; // Replace by your own 

     // Read input file into List  
     ArrayList<String> urls = new ArrayList<>(); 
     try (Stream<String> stream = Files.lines(Paths.get(sourceFileName))) { 
      stream.forEach((string) -> { 
       urls.add(string); 
      }); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     // Create thread pool 
     ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numberOfThreads); 
     List<Future<String>> resultList = new ArrayList<>(); 

     // Launch threads 
     for(String url : urls) { 
      StatusThread statusGetter = new StatusThread(url); 
      Future<String> result = executor.submit(statusGetter); 
      resultList.add(result); 
     } 

     // Use results 
     FileWriter writer; 
     writer = new FileWriter(targetFileName); 
     for (Future<String> future : resultList) { 
      try { 
       String oneResult = future.get().split("\\|")[0] + " -> " + future.get().split("\\|")[1]; 

       // Print the results to the console 
       System.out.println(oneResult); 

       // Write the result to a file 
       writer.write(oneResult + System.lineSeparator()); 

      } catch (InterruptedException | ExecutionException e) { 
       e.printStackTrace(); 
      } 
     } 
     writer.close(); 


     // Shut down the executor service 
     executor.shutdown(); 
    } 
} 

nicht vergessen zu:

  • es Erstellen Sie Ihre Eingabedatei und Punkt (c: //lines.txt)
  • Ändern Sie die Anzahl der Threads, um das beste Ergebnis
+0

Können Sie mir sagen, wenn ich die Ausgabe in eine Textdatei schreiben möchte, was ich brauche in deinem Code ändern? Das ist großartig und was ich gesucht habe. Kann ich es sogar schneller machen? –

+0

Ich habe meine Antwort aktualisiert, sodass die Ergebnisse in eine Datei (targetFileName) geschrieben werden. Für die Geschwindigkeit spielen Sie mit der Anzahl der Threads herum. Schließlich werden Sie die Leistungsgrenzen (wo die Kosten der Thread-Erstellung die Geschwindigkeit überwiegen) erreichen. Auch könnte es schnellere Lösungen geben, das ist nur mein Versuch :) – Tim

+0

Auch Sie können alles im Code ändern, es war nur ein Beispiel. Sie können den Teil "// Ergebnisse in die Konsole drucken" entfernen, wenn Sie ihn beispielsweise nicht benötigen. – Tim

1

werden Sie Probleme haben, eine Datei über Threads zu teilen. Viel besser, um die Datei zu lesen und dann einen Thread zu erzeugen, um jeden Datensatz in der Datei zu verarbeiten.

Das Erstellen eines Threads ist keine triviale Ressource, daher wäre ein Thread-Pool nützlich, damit Threads wiederverwendet werden können.

Möchten Sie, dass alle Threads in eine einzelne Datei schreiben?

Ich würde das mit einer gemeinsamen Liste zwischen den Threads und dem Schreiber tun. andere haben vielleicht eine bessere Idee.

Wie alles zu tun ist, hängt von der Java-Version ab.

+0

Ich habe nur auf Datei. Ich möchte nur davon lesen und meinen Code eingeben. Aber es sollte Fähigkeit haben, an mehreren Threads zu arbeiten bedeutet, dass ich 20000 oder mehr Domains gleichzeitig nehmen und sie verarbeiten muss, damit mein Code schneller läuft. –

1

Sie können ExecutorService verwenden und die zu verwendende Thread-Nummer festlegen.
Die ExecutorService Instanz wird für Ihre Thread-Verwaltung zuständig sein.
Sie müssen nur die Aufgaben angeben, die zum Ausführen und Aufrufen aller Aufgaben ausgeführt werden müssen
.

Wenn alle Aufgaben ausgeführt wurden, können Sie das Ergebnis erhalten.
In der call() Methode der Callable Implementierung geben wir eine String mit einem Trennzeichen zurück, um die URL und den Antwortcode der Anfrage anzugeben.
Zum Beispiel: http://example3.com||301, http://example.com||200, etc ...

ich nicht den Code geschrieben haben, eine Datei und speichern Sie in einer anderen Datei das Ergebnis der Aufgaben zu lesen. Sie sollten keine großen Schwierigkeiten haben, es zu implementieren.

Hier ist die Hauptklasse:

import java.util.HashSet; 
import java.util.List; 
import java.util.Set; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 

public class Main { 

    public static void main(String[] args) throws InterruptedException { 

     String[] hostList = { "http://example.com", "http://example2.com", "http://example3.com" }; 

     int nbThreadToUse = Runtime.getRuntime().availableProcessors() - 1; 
     ExecutorService executorService = Executors.newFixedThreadPool(nbThreadToUse); 
     Set<Callable<String>> callables = new HashSet<Callable<String>>(); 
     for (String host : hostList) { 
      callables.add(new UrlCall(host)); 
     } 

     List<Future<String>> futures = executorService.invokeAll(callables); 

     for (Future<String> future : futures) { 
      try { 
       String result = future.get(); 
       String[] keyValueToken = result.split("\\|\\|"); 
       String url = keyValueToken[0]; 
       String response = keyValueToken[1]; 
       System.out.println("url=" + url + ", response=" + response); 

      } catch (ExecutionException e) { 
       e.printStackTrace(); 
      } 
     } 

     executorService.shutdown(); 
    } 

} 

Hier ist UrlCall, die aufrufbare Implementierung einen Aufruf der URL auszuführen. UrlCall nimmt in seinem Konstruktor die URL zum Testen.

import java.io.IOException; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.util.concurrent.Callable; 

public class UrlCall implements Callable<String> { 

    private String url; 

    public UrlCall(String url) { 
     this.url = url; 
    } 

    @Override 
    public String call() throws Exception { 
     return getStatus(url); 
    } 

    private String getStatus(String url) throws IOException { 

     try { 
      URL siteURL = new URL(url); 
      HttpURLConnection connection = (HttpURLConnection) siteURL.openConnection(); 
      connection.setRequestMethod("HEAD"); 
      connection.connect(); 

      int code = connection.getResponseCode(); 
      return url + "||" + code; 

     } catch (Exception e) { 
      //FIXME to log of course 
      return url + "||exception"; 
     } 

    } 

} 
1
zu erhalten

Ich stimme dem Thread-Pool-Ansatz hier zu. Multi-Threading besteht darin, die Zeit zu nutzen, die die anderen Threads zum Warten aufwenden (ich vermute in diesem Fall: die Reaktion der entfernten Seite). Es multipliziert nicht die Verarbeitungsleistung. Dann scheinen ungefähr 10 Threads vernünftig zu sein (mehr abhängig von der Hardware).

Ein wichtiger Punkt, der in der Antwort, die ich gelesen habe, vernachlässigt worden zu sein scheint, ist, dass OP über Millionen von von Domänen spricht. Dann würde ich davon abraten, ganze Dateien im Speicher in einer Liste zu laden, die danach iteriert wird. Ich würde lieber alle in einer einzigen Schleife (Datei lesen), anstatt 3 (lesen, pingen, schreiben) zusammenführen.

stream.forEach((url) -> { 
    StatusThread statusGetter = new StatusThread(url, outputWriter); 
    Future<String> result = executor.submit(statusGetter); 
}); 

outputWriter wäre ein Typ mit einem synchronisiert Verfahren in einen Ausgangsstrom zu schreiben.

+0

Vielen Dank für Ihre Beratung. Ich werde in Bezug auf Threads beachten. –

Verwandte Themen