Java 如何将文件作为输入并在多个线程中工作?

Java 如何将文件作为输入并在多个线程中工作?,java,multithreading,io,Java,Multithreading,Io,我有以下代码来了解如何从URL获取状态代码: 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 = {

我有以下代码来了解如何从URL获取状态代码:

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

跨线程共享文件时会出现问题。最好先读取文件,然后生成一个线程来处理文件中的每条记录

创建一个线程在资源方面不是一件小事,因此线程池将非常有用,这样线程就可以重用

是否希望所有线程都写入单个文件

我会使用线程和编写器之间的共享列表来实现这一点。其他人可能有更好的想法


如何做到这一切取决于Java版本。

您将遇到跨线程共享文件的问题。最好先读取文件,然后生成一个线程来处理文件中的每条记录

创建一个线程在资源方面不是一件小事,因此线程池将非常有用,这样线程就可以重用

是否希望所有线程都写入单个文件

我会使用线程和编写器之间的共享列表来实现这一点。其他人可能有更好的想法


如何完成这一切取决于Java版本。

您可以使用
ExecutorService
并设置要使用的线程号。
ExecutorService
实例将处理线程管理
您只需要为它提供要执行的任务并调用所有任务执行

完成所有任务后,您可以得到结果。
Callable
实现的
call()
例如:
http://example3.com||301
http://example.com||200等

我没有编写读取文件并将任务结果存储在另一个文件中的代码。实施起来应该不会有很大困难

以下是主要课程:

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();
    }

}

您可以使用执行器服务
并设置要使用的线程编号。
ExecutorService
实例将处理线程管理
您只需要为它提供要执行的任务并调用所有任务执行

完成所有任务后,您可以得到结果。
Callable
实现的
call()
例如:
http://example3.com||301
http://example.com||200等

我没有编写读取文件并将任务结果存储在另一个文件中的代码。实施起来应该不会有很大困难

以下是主要课程:

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();
    }

}

这正是您想要的:

输入列表文件(c://lines.txt)

线程:

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;
    }
}
导入java.net.HttpURLConnection;
导入java.net.URL;
导入java.util.concurrent.Callable;
公共类StatusThread实现可调用{
字符串url;
公共状态线程(字符串url){
this.url=url;
}
@凌驾
公共字符串调用()引发异常{
字符串结果=”;
试一试{
URL siteURL=新URL(URL);
HttpURLConnection连接=(HttpURLConnection)siteURL.openConnection();
连接。设置请求方法(“HEAD”);
connection.connect();
int code=connection.getResponseCode();
结果=整数.toString(代码);
}捕获(例外e){
result=“->Red”+future.get().split(“\\\\”)[1];
//将结果打印到控制台
系统输出打印项次(oneResult);
//将结果写入文件
writer.write(oneResult+System.lineSeparator());
}捕获(中断异常|执行异常e){
e、 printStackTrace();
}
}
writer.close();
//关闭executor服务
executor.shutdown();
}
}
别忘了:

  • 创建输入文件并指向它(c://lines.txt)
  • 更改线程数以获得最佳结果

这就是您想要的:

输入列表文件(c://lines.txt)

线程:

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;
    }
}
导入java.net.HttpURLConnection;
导入java.net.URL;
导入java.util.concurrent.Callable;
公共类StatusThread实现可调用{
字符串url;
公共状态线程(字符串url){
this.url=url;
}
@凌驾
公共字符串调用()引发异常{
字符串结果=”;
试一试{
URL siteURL=新URL(URL);
HttpURLConnection连接=(HttpURLConnection)siteURL.openConnection();
连接。设置请求方法(“HEAD”);
connection.connect();
int code=connection.getResponseCode();
结果=整数.toString(代码);
}捕获(例外e){
result=“->Red”+future.get().split(“\\\\”)[1];
//将结果打印到控制台
系统输出打印项次(oneResult);
//将结果写入文件
writer.write(oneResult+System.lineSeparator());
}捕获(中断异常|执行异常e){
e、 printStackTrace();
}
}
writer.close();
//关闭executor服务
executor.shutdown();
}
}
别忘了:

  • 创建输入文件并指向它(c://lines.txt)
  • 更改线程数以获得最佳结果

我同意这里公开的线程池方法。 多线程包括利用其他线程等待的时间(我猜在本例中是远程站点响应)。它不会增加处理能力。那么大约有10个线程看起来是合理的(更多地取决于硬件)

在我读到的答案中,有一点似乎被忽视了,那就是OP谈论的是数以百万计的人
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;
    }
}
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();
    }
}
stream.forEach((url) -> {
     StatusThread statusGetter = new StatusThread(url, outputWriter);
     Future<String> result = executor.submit(statusGetter);
});