- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
目前我正在处理我的第一次内存泄漏,但我似乎无法修复它。我的程序应该通过名为 JukeBox
的类播放 .wav 音频文件。 JukeBox
工作正常,但每次我播放新声音时,java 在任务管理器中使用的内存量都会增加,一旦我点击 ~316,500K
我会收到以下错误System.err
终端:
Exception in thread "Thread-6" java.lang.OutOfMemoryError: Java heap space
at com.sun.media.sound.DirectAudioDevice$DirectClip.open(DirectAudioDevice.java:1135)
at JukeBox.play(JukeBox.java:53)
at Instrument.play(Instrument.java:65)
at Conductor.play(Conductor.java:78)
at Game$2.run(Game.java:42)
在我的调试器中,线程 6 是不断寻找键盘输入(特别是触发声音的线程)的两个线程之一。
这是错误后我的调试器的屏幕截图:image from debugger of threads
所以我相当确定我的问题是由于有太多打开的剪辑线程引起的,但这正是我真正困惑的地方,因为我以为我正在关闭它们,而实际上它们看起来只是卡在那里,等待。
这是我认为我要关闭剪辑的代码:
public void play(int pitch){
jukez = new JukeBox("pianoNote.wav");
Thread clipkill = new Thread() {
public void run() {
try {
Thread.sleep(jukez.getMicrosecondLength()*1000);
} catch (Exception e){System.out.println(e);}
jukez.killTheTunes();
}
};
jukez.play();
clipkill.start();
}
点唱机在这里:
public class JukeBox{
private AudioInputStream stream;
private AudioFormat format;
private DataLine.Info info;
private Clip clip;
private String name;
/**
* Constructor for objects of the class Jukebox
* @param str the filename of the wave file to pla
*/
public JukeBox(String str){
try{
stream = AudioSystem.getAudioInputStream(new File(str));
name = str;
format = stream.getFormat();
info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
} catch(Exception E){
System.out.println(E);
}
}
/**
* Returns the clip's length in microseconds.
* @return the clip's length in microseconds.
*/
public long getMicrosecondLength(){return clip.getMicrosecondLength();}
/**
* Plays the music on its own thread, enabling the game to run while music plays
*/
public void play(){
try {
clip.open(stream);
clip.start();
}
catch (Exception e) {
System.out.println(e);
}
}
/**
* Ends the music and it's thread as well
*/
public void killTheTunes(){
try{stream.close();}catch (Exception e) {
System.out.println(e);
}
clip.close();
}
/**
* Returns the filename the jukebox was initially set to play
* @return the filename the jukebox was initially set to play
*/
public String toString(){
return name;
}
}
我不确定为什么我仍然遇到堆内存问题。谢谢
编辑:
我的代码结构有点复杂,所以我会尽量解释一下。运行游戏的主要方法如下所示:
display = new Display();
copper = new Conductor();
display.main(); //sets up all the jframe things and graphics
Thread p1 = new Thread() {
public void run() {
while(true){
if(display.panel.playerClicked(1)){
display.panel.p1 = Color.black;
display.panel.p1 = copper.play(4,copper.determinePitch(display.panel.getY(1)));
display.panel.pause(250);
display.panel.p1 = Color.black;
}
}
}
};
Thread p2 = new Thread() {
public void run() {
while(true){
if(display.panel.playerClicked(2)){
display.panel.p2 = Color.black;
display.panel.p2 = copper.play(0,copper.determinePitch(display.panel.getY(2)));
display.panel.pause(250);
display.panel.p2 = Color.black;
}
}
}
};
p1.start();
p2.start();
这是检测按键移动的 Canvas 类。 Display 基本上只是初始化一个 JFrame 并向其添加一个 Canvas。
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.util.ArrayList;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import java.awt.Image;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
public class Canvas extends JPanel {
// attributes
private Rectangle player1;
private Rectangle player2;
public final int x = 800 + 200;
public final int y = 1100/2 + 200;
private boolean[] player1bools = new boolean[5];
private boolean[] player2bools = new boolean[5];
BufferedImage dimg;
Color p1 = Color.black; //these are intentionally public so game can change them
Color p2 = Color.black;
// constructor
public Canvas() {
// initialize object
player1 = new Rectangle(250, 50, 50, 50);
player2 = new Rectangle(50, 50, 50, 50);
// set canavs background colour
// add the key listener in the constructor of your canavas/panel
addKeyListener(new myKeyListener());
BufferedImage img = null;
try {
img = ImageIO.read(new File("Pencils.jpg"));
} catch (IOException e) {}
dimg = resize(img, x, y-20);
// ensure focus is on this canavas/panel for key operations.
setFocusable(true);
setBackground(new Color(0,0,0,0));
setOpaque(true);
Thread gameLoop = new Thread() {
public void run() {
while(true){
updatePlayers();
repaint();
pause(20);
}
}
};
gameLoop.start();
}
public int getY(int i){
if(i == 1){return player1.y;}
if(i == 2){return player2.y;}
return -1;
}
public boolean isOptimizedDrawingEnabled(){return false;}
/**
* This method was made by David Kroukamp on
* http://stackoverflow.com/questions/14548808/scale-the-imageicon-automatically-to-label-size
*/
public static BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(image, 0, 0, width, height, null);
g2d.dispose();
return bi;
}
private void updatePlayers() {
if (player1bools[0]) {
moveX(-5, player1);
}
if (player1bools[2]) {
moveX(5, player1);
}
if (player1bools[1]) {
moveY(-5, player1);
}
if (player1bools[3]) {
moveY(5, player1);
}
if (player2bools[0]) {
moveX(-5, player2);
}
if (player2bools[2]) {
moveX(5, player2);
}
if (player2bools[1]) {
moveY(-5, player2);
}
if (player2bools[3]) {
moveY(5, player2);
}
}
// painting
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
graphics.clearRect(0, 0, getWidth(), getHeight()); //clears the trails
graphics.drawImage(dimg,0,0,null);
Graphics2D graphics2d = (Graphics2D) graphics;
graphics.setColor(p1);
graphics2d.fill(player1);
graphics.setColor(p2);
graphics2d.fill(player2);
// */
}
// function which essentially re-creates rectangle with varying x
// orientations. (x-movement)
public void moveX(int mutationDistance, Rectangle sampleObject) {
//I don't want horizontal movement to work
/*
sampleObject.setBounds(sampleObject.x + mutationDistance,
sampleObject.y, sampleObject.width, sampleObject.height);
*/
}
// function which essentially re-creates rectangle with varying y
// orientations. (y-movement)
public void moveY(int mutationDistance, Rectangle sampleObject) {
if(sampleObject.y < 0) {
sampleObject.y = 0;
}
else if(sampleObject.y > 670) {
sampleObject.y = 670;
}
sampleObject.setBounds(sampleObject.x, sampleObject.y
+ mutationDistance, sampleObject.width, sampleObject.height);
}
public boolean playerClicked(int i){
if(i == 1){return player1bools[4];}
if(i == 2){return player2bools[4];}
return false;
}
// listener
private class myKeyListener implements KeyListener {
// implement all the possible actions on keys
public void keyPressed(final KeyEvent keyEvent) {
if (keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE) {
System.exit(0);
}
if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
player1bools[2] = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
player1bools[0] = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
player1bools[1] = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
player1bools[3] = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_SLASH) {
player1bools[4] = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_D) {
player2bools[2] = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_A) {
player2bools[0] = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_W) {
player2bools[1] = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_S) {
player2bools[3] = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_F) {
player2bools[4] = true;
}
}
public void keyReleased(KeyEvent keyEvent) {
if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
player1bools[2] = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
player1bools[0] = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
player1bools[1] = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
player1bools[3] = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_SLASH) {
player1bools[4] = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_D) {
player2bools[2] = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_A) {
player2bools[0] = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_W) {
player2bools[1] = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_S) {
player2bools[3] = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_F) {
player2bools[4] = false;
}
}
public void keyTyped(KeyEvent keyEvent) {
}
}
public static void pause(int secs) {
try {
Thread.sleep(secs);
} catch (Exception e) {}
}
}
最后是 Conductor,它管理这里的乐器:
public class Conductor
{
private ArrayList<Instrument> symphony;
/**
* Constructor for objects of class Conductor, initializes the instruments
*/
public Conductor()
{
ArrayList<String> pianoList = new ArrayList<String>();
for(int i = 1; i <= 11; i++){
pianoList.add("piano"+i);
}
ArrayList<String> bassList = new ArrayList<String>();
for(int i = 1; i <= 11; i++){
bassList.add("bass"+i);
}
ArrayList<String> guitarList = new ArrayList<String>();
for(int i = 1; i <= 11; i++){
guitarList.add("guitar"+i);
}
ArrayList<String> percList = new ArrayList<String>();
for(int i = 1; i <= 11; i++){
percList.add("perc"+i);
}
ArrayList<String> vibeList = new ArrayList<String>();
for(int i = 1; i <= 11; i++){
vibeList.add("vibe"+i);
}
Instrument piano = new Instrument(pianoList, new Color(19,130,206));
Instrument bass = new Instrument(bassList, new Color(100,83,38));
Instrument guitar = new Instrument(guitarList, new Color(244,184,16));
Instrument perc = new Instrument(percList, new Color(24,57,165));
Instrument vibe = new Instrument(vibeList, new Color(57,24,135));
symphony = new ArrayList<Instrument>();
symphony.add(piano);
symphony.add(bass);
symphony.add(guitar);
symphony.add(perc);
symphony.add(vibe);
}
public static int determinePitch(int i){
if(i == -1){return i;}
if(i>600){return 1;}
if(i>535){return 2;}
if(i>470){return 3;}
if(i>410){return 4;} //these numbers correspond to the approximate heights of the colors in the background image
if(i>345){return 5;}
if(i>275){return 6;}
if(i>215){return 7;}
if(i>155){return 8;}
if(i>90){return 9;}
if(i>25){return 10;}
return 11;
}
/**
* Calls an instrument and makes it play a noise
* @param inst the instrument index to play
* @param pitch the pitch for the instrument to play
*/
public Color play(int inst, int pitch){
symphony.get(inst).play(pitch);
return symphony.get(inst).getColor();
}
}
所以对于结构的整体运行:
控制玩家的线程会检测他们各自的玩家是否按下了触发键。如果是这样,他们会请指挥演奏乐器。他们还改变了该玩家矩形的颜色。当指挥演奏乐器时,它使用 Instrument 的 play 方法,该方法调用乐器的 JukeBox 方法,该方法使用导致崩溃的剪辑。
最佳答案
Thread.sleep() 以毫秒为参数,所以行:
Thread.sleep(jukez.getMicrosecondLength()*1000);
应该是:
Thread.sleep(jukez.getMicrosecondLength()/1000);
您的代码中可能还存在其他问题,但目前您永远不会调用 killTheTunez()
,因为您等待的时间太长了百万倍。
关于java - 防止可能由于线程引起的堆内存不足异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37234143/
我将 Bootstrap 与 css 和 java 脚本结合使用。在不影响前端代码的情况下,我真的很难在css中绘制这个背景。在许多问题中,人们将宽度和高度设置为 0%。但是由于我的导航栏,我不能使用
我正在用 c 编写一个程序来读取文件的内容。代码如下: #include void main() { char line[90]; while(scanf("%79[^\
我想使用 javascript 获取矩阵数组的所有对 Angular 线。假设输入输出如下: input = [ [1,2,3], [4,5,6], [7,8,9], ] output =
可以用pdfmake绘制lines,circles和other shapes吗?如果是,是否有documentation或样本?我想用jsPDF替换pdfmake。 最佳答案 是的,有可能。 pdfm
我有一个小svg小部件,其目的是显示角度列表(参见图片)。 现在,角度是线元素,仅具有笔触,没有填充。但是现在我想使用一种“内部填充”颜色和一种“笔触/边框”颜色。我猜想line元素不能解决这个问题,
我正在为带有三角对象的 3D 场景编写一个非常基本的光线转换器,一切都工作正常,直到我决定尝试从场景原点 (0/0/0) 以外的点转换光线。 但是,当我将光线原点更改为 (0/1/0) 时,相交测试突
这个问题已经有答案了: Why do people write "#!/usr/bin/env python" on the first line of a Python script? (22 个回
如何使用大约 50 个星号 * 并使用 for 循环绘制一条水平线?当我尝试这样做时,结果是垂直(而不是水平)列出 50 个星号。 public void drawAstline() { f
这是一个让球以对角线方式下降的 UI,但球保持静止;线程似乎无法正常工作。你能告诉我如何让球移动吗? 请下载一个球并更改目录,以便程序可以找到您的球的分配位置。没有必要下载足球场,但如果您愿意,也可以
我在我的一个项目中使用 Jmeter 和 Ant,当我们生成报告时,它会在报告中显示 URL、#Samples、失败、成功率、平均时间、最短时间、最长时间。 我也想在报告中包含 90% 的时间线。 现
我有一个不寻常的问题,希望有人能帮助我。我想用 Canvas (android) 画一条 Swing 或波浪线,但我不知道该怎么做。它将成为蝌蚪的尾部,所以理想情况下我希望它的形状更像三角形,一端更大
这个问题已经有答案了: Checking Collision of Shapes with JavaFX (1 个回答) 已关闭 8 年前。 我正在使用 JavaFx 8 库。 我的任务很简单:我想检
如何按编号的百分比拆分文件。行数? 假设我想将我的文件分成 3 个部分(60%/20%/20% 部分),我可以手动执行此操作,-_-: $ wc -l brown.txt 57339 brown.tx
我正在努力实现这样的目标: 但这就是我设法做到的。 你能帮我实现预期的结果吗? 更新: 如果我删除 bootstrap.css 依赖项,问题就会消失。我怎样才能让它与 Bootstrap 一起工作?
我目前正在构建一个网站,但遇到了 transform: scale 的问题。我有一个按钮,当用户将鼠标悬停在它上面时,会发生两件事: 背景以对 Angular 线“扫过” 按钮标签颜色改变 按钮稍微变
我需要使用直线和仿射变换绘制大量数据点的图形(缩放图形以适合 View )。 目前,我正在使用 NSBezierPath,但我认为它效率很低(因为点在绘制之前被复制到贝塞尔路径)。通过将我的数据切割成
我正在使用基于 SVM 分类的 HOG 特征检测器。我可以成功提取车牌,但提取的车牌除了车牌号外还有一些不必要的像素/线。我的图像处理流程如下: 在灰度图像上应用 HOG 检测器 裁剪检测到的区域 调
我有以下图片: 我想填充它的轮廓(即我想在这张图片中填充线条)。 我尝试了形态学闭合,但使用大小为 3x3 的矩形内核和 10 迭代并没有填满整个边界。我还尝试了一个 21x21 内核和 1 迭代,但
我必须找到一种算法,可以找到两组数组之间的交集总数,而其中一个数组已排序。 举个例子,我们有这两个数组,我们向相应的数字画直线。 这两个数组为我们提供了总共 7 个交集。 有什么样的算法可以帮助我解决
简单地说 - 我想使用透视投影从近裁剪平面绘制一条射线/线到远裁剪平面。我有我认为是使用各种 OpenGL/图形编程指南中描述的方法通过单击鼠标生成的正确标准化的世界坐标。 我遇到的问题是我的光线似乎
我是一名优秀的程序员,十分优秀!