Java程序内存占用过高原因分析

今天在做一款基于Java Swing界面的烟花游戏时,发现在播放音频的过程中界面异常卡顿,查看任务管理器,发现GPU占用几乎高达百分之百,于是立刻想到应该是由于循环内创建对象导致的内存溢出
音频播放类代码如下 BackGroundSound

// 音频播放类
import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Optional;

public class BackGroundSound {
    
    public void setSoundState(String filePath,String state) throws MalformedURLException {
        
        URL url = new File(filePath).toURL();
        AudioClip audioClip = Applet.newAudioClip(url);
        
        if(state.equals("start")){
            audioClip.play();
        }else if (state.equals("stop")){
            audioClip.stop();
        }
    }
}

调用如下:

//按钮监听事件
btnStart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //System.out.println("button被按下了");
                btnStop.setDoubleBuffered(true);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        state = 1;
                        while (state==1) {
                            try {
                                Thread.sleep(200);
                                if(fireworks.getY()==595||fireworks1.getY()==580||fireworks2.getY()==601||fireworks3.getY()==616){
                               		new BackGroundSound().
                               		backGroundSound.setSoundState("sounds/9800.wav","start");
                                    new BackGroundSound().
                                    backGroundSound.setSoundState("sounds/y939.wav","stop");
                                }
                                if(fireworks.getY()==190||fireworks1.getY()==240||fireworks2.getY()==133||fireworks3.getY()==208){
                                	new BackGroundSound().
                                    backGroundSound.setSoundState("sounds/9800.wav","stop");
                                    new BackGroundSound().
                                    backGroundSound.setSoundState("sounds/y939.wav","start");
                                }
                            } catch (InterruptedException ex) {
                                throw new RuntimeException(ex);
                            } catch (MalformedURLException ex) {
                                throw new RuntimeException(ex);
                            }
                            SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    repaint();
                                }
                            });
                        }
                    }
                }).start();
            }
        });

在上述的判断代码中,看上去每个if语句里创建了2个对象,但实际上调用的BackGroundSound 类的代码中又创建了2个对象,相当于一次判断中创建了4个对象,这还不算while循环,于是对代码进行一番爆改,将BackGroundSound提取出来作为成员变量,按钮监听整改代码如下 :

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.MalformedURLException;
import java.util.Random;

public class FireworksWindow extends JFrame {
	/*
	具体代码省略
	*/
	...
	BackGroundSound backGroundSound = new BackGroundSound();
	
	public FireworksWindow(){
		...
		btnStart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //System.out.println("button被按下了");
                btnStop.setDoubleBuffered(true);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        state = 1;
                        while (state==1) {
                            try {
                                Thread.sleep(200);
                                if(fireworks.getY()==595||fireworks1.getY()==580||fireworks2.getY()==601||fireworks3.getY()==616){
                                    backGroundSound.setSoundState("sounds/9800.wav","start");
                                    backGroundSound.setSoundState("sounds/y939.wav","stop");
                                }
                                if(fireworks.getY()==190||fireworks1.getY()==240||fireworks2.getY()==133||fireworks3.getY()==208){
                                    backGroundSound.setSoundState("sounds/9800.wav","stop");
                                    backGroundSound.setSoundState("sounds/y939.wav","start");
                                }
                            } catch (InterruptedException ex) {
                                throw new RuntimeException(ex);
                            } catch (MalformedURLException ex) {
                                throw new RuntimeException(ex);
                            }
                            SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    repaint();
                                }
                            });
                        }
                    }
                }).start();
            }
        });
	}

}

同样,对BackGroundSound类中的代码进行如下整改:

import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Optional;

public class BackGroundSound {
	/*
	将URL和AudioCilp 对象提取作为成员变量
	*/
    private URL url;
    private AudioClip audioClip;
    
    public void setSoundState(String filePath,String state) throws MalformedURLException {
    	/*
    	调用Optional类中的方法判断对象是否存在,如果不存在,则创建
    	*/
        boolean urlObj = Optional.ofNullable(url).isPresent();
        boolean audioClipObj = Optional.ofNullable(audioClip).isPresent();
        
        if(!urlObj&&!audioClipObj){
        url = new File(filePath).toURL();
        audioClip = Applet.newAudioClip(url);
        }
        
        if(state.equals("start")){
            audioClip.play();
        }else if (state.equals("stop")){
            audioClip.stop();
        }
    }
}

这样一来,调用setSoundState()方法,能每个保证只创建一次,便解决了循环创建对象导致的CPU和内存占用过高的问题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值