Skip to content

Instantly share code, notes, and snippets.

@dnslin

dnslin/run.java Secret

Last active April 16, 2024 08:32
Show Gist options
  • Save dnslin/fe657f9df08f4286c197c5e9e5fd6a51 to your computer and use it in GitHub Desktop.
Save dnslin/fe657f9df08f4286c197c5e9e5fd6a51 to your computer and use it in GitHub Desktop.
package in.dnsl;
import cn.hutool.log.Log;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import me.kuku.utils.Lists;
import me.kuku.utils.OkHttpUtils;
import okhttp3.Headers;
import okhttp3.Response;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Main {
static Log log = Log.get();
static final Gson gson = new Gson();
static List<Image> images = null;
static int maxThreads = 96; // 控制固定线程池的大小
static ExecutorService virtualThreadPool = Executors.newFixedThreadPool(maxThreads, Thread.ofVirtual().factory());
static String filePath = "/root/java_work/imglist/";
// 失败list
static List<String> failList = Lists.newArrayList();
public static void main(String[] args) {
OkHttpUtils.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890)));
List<String> types = List.of(".jpg", ".png");
try {
images = gson.fromJson(new FileReader("output-2024-4-16.json"), new TypeToken<List<Image>>() {
}.getType());
} catch (IOException e) {
log.info("读取文件失败: {}", e.getMessage());
return;
}
log.info("加载到的图片数量: {}", images.size());
images.forEach(image -> virtualThreadPool.submit(() -> {
for (String type : types) {
String url = convertPreviewToImageUrl(image.getHref(), type);
if (attemptToDownloadImage(url, 0)) {
image.setSourceUrl(url); // 更新Image对象
break;
}
}
}));
virtualThreadPool.shutdown();
try {
// 等待60秒看线程池是否完全关闭
if (!virtualThreadPool.awaitTermination(2, TimeUnit.HOURS)) {
log.info("线程池在60秒内未完全关闭,尝试立即关闭所有正在执行的任务");
virtualThreadPool.shutdownNow(); // 尝试取消正在执行的任务
// 再等待60秒确认线程池是否关闭
if (!virtualThreadPool.awaitTermination(2, TimeUnit.MINUTES)) {
log.info("线程池任务无法终止");
}
}
} catch (InterruptedException ie) {
virtualThreadPool.shutdownNow(); // 响应中断,尝试立即关闭
Thread.currentThread().interrupt(); // 保留中断状态
}
// 将更新后的images列表写回到JSON文件
writeImagesToJson(images, "output-2024-4-16-ok.json");
writeImagesToJson(failList, "output-2024-4-16-fail.json");
}
private static boolean attemptToDownloadImage(String url, int retryCount) {
if (retryCount >= 3) {
log.info("重试次数过多,放弃下载: {}", url);
failList.add(url);
return false;
}
try (Response response = OkHttpUtils.get(url, Headers.of("Connection", "close"))) {
switch (response.code()) {
case 200:
log.info("成功下载图片: {}", url);
byte[] bytes = Objects.requireNonNull(response.body()).bytes();
writeImageToFile(bytes, url.substring(url.lastIndexOf('/') + 1));
return true;
case 404:
log.info("图片不存在: {}", url);
return false;
case 429:
log.info("请求过于频繁,需要稍后重试: {}", url);
handleRateLimiting();
return attemptToDownloadImage(url, retryCount + 1);
default:
log.info("其他HTTP响应: {}", response.code());
return false;
}
} catch (Exception e) {
log.error("请求图片时出错: {}", e.fillInStackTrace());
handleRateLimiting();
return attemptToDownloadImage(url, retryCount + 1);
}
}
private static void handleRateLimiting() {
try {
log.info("等待5秒后重试");
Thread.sleep(5000); // 延迟5秒后重试
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public static String convertPreviewToImageUrl(String previewUrl, String type) {
String id = previewUrl.substring(previewUrl.lastIndexOf('/') + 1);
return String.format("https://w.wallhaven.cc/full/%s/wallhaven-%s%s", id.substring(0, 2), id, type);
}
public static void writeImagesToJson(List<?> objects, String fileName) {
try (FileWriter writer = new FileWriter(fileName)) {
gson.toJson(objects, writer);
} catch (IOException e) {
log.error("写入文件时出错: {}", e.getMessage());
}
}
public static void writeImageToFile(byte[] bytes, String fileName) {
try (FileOutputStream fos = new FileOutputStream(filePath + fileName)) {
fos.write(bytes);
log.info("成功写入文件: {}", fileName);
} catch (IOException e) {
log.error("写入文件时出错: {}", e.getMessage());
}
}
}
@dnslin
Copy link
Author

dnslin commented Apr 16, 2024

[arthas@293573]$ thread -n 3
"arthas-command-execute" Id=213 cpuUsage=0.43% deltaTime=0ms time=19ms RUNNABLE
at java.management@21.0.2/sun.management.ThreadImpl.dumpThreads0(Native Method)
at java.management@21.0.2/sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:482)
at com.taobao.arthas.core.command.monitor200.ThreadCommand.processTopBusyThreads(ThreadCommand.java:206)
at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:122)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)
at java.base@21.0.2/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base@21.0.2/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base@21.0.2/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
at java.base@21.0.2/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base@21.0.2/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base@21.0.2/java.lang.Thread.runWith(Thread.java:1596)
at java.base@21.0.2/java.lang.Thread.run(Thread.java:1583)

"OkHttp w.wallhaven.cc" Id=198 cpuUsage=0.01% deltaTime=0ms time=79ms BLOCKED on okhttp3.internal.http2.Http2Stream@1a2677fc owned by "ForkJoinPool-1-worker-7" Id=115
at app//okhttp3.internal.http2.Http2Stream$FramingSource.receive$okhttp(Http2Stream.kt:425)
- blocked on okhttp3.internal.http2.Http2Stream@1a2677fc
at app//okhttp3.internal.http2.Http2Stream.receiveData(Http2Stream.kt:276)
at app//okhttp3.internal.http2.Http2Connection$ReaderRunnable.data(Http2Connection.kt:650)
at app//okhttp3.internal.http2.Http2Reader.readData(Http2Reader.kt:180)
at app//okhttp3.internal.http2.Http2Reader.nextFrame(Http2Reader.kt:119)
at app//okhttp3.internal.http2.Http2Connection$ReaderRunnable.invoke(Http2Connection.kt:618)
at app//okhttp3.internal.http2.Http2Connection$ReaderRunnable.invoke(Http2Connection.kt:609)
at app//okhttp3.internal.concurrent.TaskQueue$execute$1.runOnce(TaskQueue.kt:98)
at app//okhttp3.internal.concurrent.TaskRunner.runTask(TaskRunner.kt:116)
at app//okhttp3.internal.concurrent.TaskRunner.access$runTask(TaskRunner.kt:42)
at app//okhttp3.internal.concurrent.TaskRunner$runnable$1.run(TaskRunner.kt:65)
at java.base@21.0.2/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base@21.0.2/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base@21.0.2/java.lang.Thread.runWith(Thread.java:1596)
at java.base@21.0.2/java.lang.Thread.run(Thread.java:1583)

"OkHttp w.wallhaven.cc" Id=189 cpuUsage=0.01% deltaTime=0ms time=399ms BLOCKED on okhttp3.internal.http2.Http2Stream@4691d904 owned by "ForkJoinPool-1-worker-13" Id=121
at app//okhttp3.internal.http2.Http2Stream$FramingSource.receive$okhttp(Http2Stream.kt:425)
- blocked on okhttp3.internal.http2.Http2Stream@4691d904
at app//okhttp3.internal.http2.Http2Stream.receiveData(Http2Stream.kt:276)
at app//okhttp3.internal.http2.Http2Connection$ReaderRunnable.data(Http2Connection.kt:650)
at app//okhttp3.internal.http2.Http2Reader.readData(Http2Reader.kt:180)
at app//okhttp3.internal.http2.Http2Reader.nextFrame(Http2Reader.kt:119)
at app//okhttp3.internal.http2.Http2Connection$ReaderRunnable.invoke(Http2Connection.kt:618)
at app//okhttp3.internal.http2.Http2Connection$ReaderRunnable.invoke(Http2Connection.kt:609)
at app//okhttp3.internal.concurrent.TaskQueue$execute$1.runOnce(TaskQueue.kt:98)
at app//okhttp3.internal.concurrent.TaskRunner.runTask(TaskRunner.kt:116)
at app//okhttp3.internal.concurrent.TaskRunner.access$runTask(TaskRunner.kt:42)
at app//okhttp3.internal.concurrent.TaskRunner$runnable$1.run(TaskRunner.kt:65)
at java.base@21.0.2/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base@21.0.2/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base@21.0.2/java.lang.Thread.runWith(Thread.java:1596)
at java.base@21.0.2/java.lang.Thread.run(Thread.java:1583)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment