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