当前位置: 首页 > 知识库问答 >
问题:

Java画图“结巴”-列表并发

楚嘉胜
2023-03-14

我的一个应用程序通过读取数组列表将对象绘制到屏幕上:

简单代码摘要:

@Override
public synchronized void paintComponent(Graphics g) {
  for(Object gO:paintList) {
    g.drawImage( gO.getObjImage(), gO.getXLoc(), gO.getYLoc(), outer.getTransparent(), null);
  }
}

问题是每次用户点击鼠标时我都会添加更多的对象,所以如果用户点击的速度足够快,我会导致程序绘画结结巴巴,因为它在写入时无法读取(arrayList是同步的)。开发人员处理这种并发问题的常用做法是什么?

编辑:下面是调用重新绘制的代码:

byte ticks = 0;
    while(true) {
        currentTime = System.nanoTime();
        if(ticks == 25) {
            drawPanel.repaint();
            ticks = 0;
        } else if (ticks%5 == 0) {//if ticks is a multiple of 5 (5,10,15,...)
            drawPanel.operations();
            ticks++;
        } else if(ticks < 25) {
            ticks++;
        }
        try {
            /*
            Refer to: 'http://stackoverflow.com/questions/1036754/difference-between-wait-and-sleep'
            on differences between Thread.sleep() and wait()
            */
            wait(1);//old timings: (long)(refreshRate*1000)
        } catch (InterruptedException ex) {
            Logger.getLogger(DeathWish.class.getName()).log(Level.SEVERE, null, ex);
        }
        //Debugging
        //System.out.println(ticks);
        currentTime = System.nanoTime();

*其中operations()计算“paintable”对象属性的更改,移除满足特定条件的对象,并将新对象添加到“paint”列表中。在我看来,加法和写法应该分开?如果没有足够的信息,我可以发布operations()方法,但我尽量不发布大量的代码,这样更容易解释。

共有1个答案

周和安
2023-03-14

我想你在同步方面有点不对劲:

  • ArrayList是不同步实现的列表
  • 同步方法意味着每次只有一个线程可以访问该方法,但函数中的变量根本不同步

您想要的是临时同步您的列表。

你可以这样做:

@Override
public void paintComponent(Graphics g) {
  synchronized(paintList) {
    for(Object gO:paintList) {
      g.drawImage( gO.getObjImage(), gO.getXLoc(), gO.getYLoc(), outer.getTransparent(), null);
    }
  }
}

在添加对象的代码中,您的列表也做了一些相同的操作。

从此处编辑:

如果您想要删除add线程和paint线程之间的所有并发问题,下面是您可以做的:

在添加图像的方法中:

public synchronized void addImage(...) {
  Something newImage = .....
  List<Something> newPaintList = new ArrayList<>(paintList.size() + 1);
  newPaintList.addAll(paintList);
  newPaintList.add(newImage);
  paintList = newPaintList;
}

并且在paint方法中,去掉同步部分。

@Override
public void paintComponent(Graphics g) {
  for(Object gO:paintList) {
    g.drawImage( gO.getObjImage(), gO.getXLoc(), gO.getYLoc(), outer.getTransparent(), null);
  }
}

这样,读取和写入之间就不会有任何并发,因为对paintList执行的唯一操作是读取。

应该同步Addmage以避免两个不同的线程同时添加图像,这可能会忽略一个Addmage。

 类似资料:
  • 实现信息:我已经实现了一个3窗格布局,以下是CommonsWare对他自己的问题的回应:Gmail三片段动画场景的完整工作示例? 总体而言,我的布局由以下级别(1到3)组成: (侧抽屉UI模式)隐藏在左侧的片段,而作为存放3窗格布局的片段。 在内部:(每行具有3个文本视图)、(每行具有8个文本视图)、。 和使用从每个列表中的加载数据。还在需要时调用带有数据的游标。所以我甚至没有实现自定义(这样设计

  • 问题内容: 我有一个显示两个相同类型的。当您点击其中一个视图时,它们会通过动画改变其高度。 但是,这些视图嵌入的对象没有动画,这会导致丑陋的毛刺,因为该行的高度会立即更改,而该行中的实际视图则具有动画效果: 我也该如何制作动画?我尝试在其中添加修饰符,但没有任何作用。 我也不想将其移出视图。该视图应该是独立的,不应依赖其他视图来控制它(我认为这就是MVVM的目的) 谢谢! 问题答案: 解决方案是通

  • 双非本科,参加了无数场面试,以下是最近面阿里的总结: 阿里 面经1 简单介绍项目 知道哪些数据结构以及他们的特点 链表增删快,那如何提高其查询效率,有没有什么想法? B+树了解吗?B+树如何范围查询?B+树退化的极端情况是什么? 跳表了解吗? 大顶堆、小顶堆了解吗? 实现长地址请求到服务端,然后服务端重定向短地址给客户端,如何实现长短地址的互相映射? 那我现在有10份数据,有1000个线程来争抢,

  • 图表画布 由一个画布和一个工具栏组成,让你设计图表,例如添加对象、设置图表格式和打印模型等。一个模型文件可以有多个图表。在模型中,每一个图表是由一个选项卡来表示。若要创建一个新的图表,从模型的菜单选择 文件 -> 新建图表。 创建表 要创建一个新的表,从图表工具栏点击 按钮和点击画布的任何位置。 你可以从浏览器的模型选项卡添加一个现有的表,简单地从模型选项卡拖放表到画布。 如果图表符号设置为默认,

  • 我想按id分组。 结果应如下所示: 静态编程语言中最惯用的方法是什么?

  • 前言:所以我有这个,其实应用程序并不是那么重要,它是一个tcp侦听器,整天用一些硬件聊天。但它也有一些展示的东西。显示屏在屏幕的不同区域显示不同的自定义节点,屏幕底部是一个网格,显示一些“东西”,但当没有任何“东西”时,它会在屏幕上滚动一些文本。 问题:正如我将在我构建时间线的方法中发布的那样,有一个Text元素可以在整个屏幕上从右向左过渡。这在第一个小时或可能两个小时内按预期工作,但过了一段时间