Java 下载会导致非常小的文件出现滞后峰值



编辑:我决定删除Minecraft标签。虽然这是 Minecraft mod 的代码,但我遇到的代码与核心 Java 中的函数有关,而不是 Minecraft 本身中的任何内容。

所以,我昨晚发布了一个关于我编写 Minecraft mod 函数的问题,以允许我们实现自己的斗篷,多亏了你们中的一些人,我才能让它工作。我从那里塞满了代码,并找到了一种方法,使其尽可能小,同时产生相同的结果。我还发现了如何直接从下载流中读取文件而不是复制文件。伟大?嗯,没有。现在我能够正确测试所有内容并读取我的文件,我遇到了另一个问题。虽然一切正常,但每当我的代码运行时,它会导致延迟峰值高达 2-4 秒。我环顾四周,发现了有关下载缓慢的问题,但没有关于应用程序在短时间内完全冻结的问题。由于每当玩家首次出现在屏幕上时都会运行此操作,因此这可能会重复。我正在尝试修复代码并以不同的方式重新排列了无数次,但它不会消失。

这是代码。简而言之,它会检查玩家的帐户上是否有官方的Mojang斗篷。如果他们没有,那么它会运行我的代码来检查他们是否有我们的自定义斗篷之一,确切地说,当运行时,就是游戏出现滞后峰值的时候。请注意,如果玩家有来自 Mojang 的斗篷,我的代码永远不会运行,我已经尝试禁用我的代码并只运行下载他们的 Mojang 斗篷以供使用的代码,所以我知道这部分不会导致滞后,它只是我的代码。即使他们在我的代码下没有自定义斗篷,它也总是会导致滞后。我想不出为什么;文件非常小! ...在写这篇文章时,我决定测试一些东西,所以我在我的getCustomCapes方法中禁用了player.cloakUrl变量设置行。当然,滞后仍然发生,所以我认为滞后是由检查播放器 UUID 是否与下载的 .txt 文件中的行匹配引起的。我相信从.txt文件检查和下载的代码行是这里滞后的罪魁祸首。请注意,我正在从流式传输的在线文件中读取,而不是将它们永久保存到计算机,因为它们不需要。每次调用此代码时都会读取它们,并且需要保持这种状态。

事不宜迟,这里是代码。

编辑:我试图将.close((命令添加到流中,但没有成功。

public static void getSkin(final GameProfile profile, EntityPlayer player) {
final Map<Type, MinecraftProfileTexture> map = Maps.<Type, MinecraftProfileTexture>newHashMap();
//  (Here's where some skin-related code would be but I cut it out for easier reading, 
//  it has nothing to do with this situation so don't worry about that.)
if (map.containsKey(Type.CAPE))
{
MinecraftProfileTexture texture = (MinecraftProfileTexture)map.get(Type.CAPE);
player.cloakUrl = texture.getUrl();
return;
} else {
getCustomCapes(profile, player); //Commenting this fixes the lag, proving it's my code that causes it.
}
}
public static void getCustomCapes(final GameProfile profile, EntityPlayer player) {
InputStream staff;
InputStream contest;
try {
contest = new URL("https://www.dropbox.com/s/kvvkfk6emms3qg5/contest.txt?dl=1").openStream();
StringWriter contestUUIDs = new StringWriter();
IOUtils.copy(contest, contestUUIDs, StandardCharsets.UTF_8);
if (contestUUIDs.toString().contains(profile.getId().toString()))
{
player.cloakUrl = "https://www.dropbox.com/s/a4d3agty57sd4a8/contest.png?dl=1";
// Commenting out the above line doesn't seem to help any, as stated before.
return;
}
staff = new URL("https://www.dropbox.com/s/q6f4729i2zu02nz/staff.txt?dl=1").openStream();
StringWriter staffUUIDs = new StringWriter();
IOUtils.copy(staff, staffUUIDs, StandardCharsets.UTF_8);
if (staffUUIDs.toString().contains(profile.getId().toString()))
{
player.cloakUrl = "https://www.dropbox.com/s/42jn5r7fs6k5f4l/staff.png?dl=1";
// Commenting out the above line doesn't seem to help any, as stated before.
return;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

多么古老的线程,嗯?因此,在获得更多经验后,我决定回到这个问题,说我已经找到了解决方案。这是我修复它的方法:线程魔法!ug_不久前似乎向我提出了这个建议,但当时我根本不明白。我使用了一些方法使用特殊变量启动线程,这些变量在完成后设置玩家的属性,从而消除了滞后。此外,我重写了cape .txts的工作方式,使其效率更高。您可能会注意到现在有一个文件,该文件控制所有内容,而不是每个列表都有自己的文件。这是我的代码。首先,上面的 get skin 方法几乎完全被刮掉了,我添加了一个新的方法,因为创建 GameProfile 会向 Mojang 的 API 发送请求,导致一点延迟,所以我这样做是为了让这个线程也可以生成配置文件:

public static void getSkin(final GameProfile profile, EntityPlayer player) {
ThreadFetchSkins skinThread = new ThreadFetchSkins();
skinThread.start(player, profile, mc);
}
public static void getSkinFromUUIDAndName(UUID uuid, String username, EntityPlayer player) {
ThreadFetchSkins skinThread = new ThreadFetchSkins();
skinThread.start(uuid, username, player, mc);
}

然后,这是线程。

public class ThreadFetchSkins extends Thread {
public static TreeMap<UUID, String> customCapes = new TreeMap<UUID, String>();
private EntityPlayer thePlayer;
private GameProfile theProfile;
private Minecraft mc;

private boolean createProfile = false;
private UUID id;
private String name;

public ThreadFetchSkins() {
setName("Cape data download thread");
setDaemon(true);
}

public void run() {
if(createProfile) {
theProfile = new GameProfile(id, name);
}
final Map<Type, MinecraftProfileTexture> map = Maps.<Type, MinecraftProfileTexture>newHashMap();
theProfile.getProperties().clear();
theProfile.getProperties().putAll(SkinManager.getProfileProperties(theProfile));
map.putAll(mc.sessionService.getTextures(theProfile, false));

//Removed "secure" textures grab

if (map.containsKey(Type.SKIN))
{
MinecraftProfileTexture texture = (MinecraftProfileTexture)map.get(Type.SKIN);
thePlayer.skinUrl = texture.getUrl();
String grab = texture.getMetadata("model");
// Currently returns null for steve skin
thePlayer.modelAlex = !(grab == null);
thePlayer.worldObj.obtainEntitySkin(thePlayer);
}
if (map.containsKey(Type.CAPE))
{
MinecraftProfileTexture texture = (MinecraftProfileTexture)map.get(Type.CAPE);
thePlayer.cloakUrl = texture.getUrl();
thePlayer.worldObj.obtainEntitySkin(thePlayer);
}
else {
grabCustomCapes();
}
}
public void grabCustomCapes() {
try {
URL capeDownload = new URL("https://www.dropbox.com/s/q6f4729i2zu02nz/capes.txt?dl=1");
String capeFolder = Minecraft.getMinecraftDir().getPath() + "/NFCCapes";
FileUtils.forceMkdir(new File(capeFolder));
FileUtils.copyURLToFile(capeDownload, new File(capeFolder + "/capes.txt"));
InputStream fileOS = new FileInputStream(capeFolder + "/capes.txt");
BufferedReader buf = new BufferedReader(new InputStreamReader(fileOS));

String line = buf.readLine();
customCapes.clear();
while(line != null) {
String[] data = line.split(";");
customCapes.put(UUID.fromString(data[1]), data[2]);
line = buf.readLine();
}
fileOS.close();
FileUtils.getFile(capeFolder).delete();

if(customCapes.get(theProfile.getId()) != null) {
thePlayer.cloakUrl = customCapes.get(theProfile.getId());
thePlayer.worldObj.obtainEntitySkin(thePlayer);
}
} catch (MalformedURLException e) {
e.printStackTrace();
return;
} catch (IOException e) {
e.printStackTrace();
return;
}
}

public void start(EntityPlayer player, final GameProfile profile, Minecraft minecraft) {
thePlayer = player;
theProfile = profile;
mc = minecraft;
super.start();
}

public void start(UUID uuid, String username, EntityPlayer player, Minecraft minecraft) {
id = uuid;
name = username;
thePlayer = player;
mc = minecraft;
createProfile = true;
super.start();
}
}

最新更新