用java线程绘制图案_关于多线程:使用线程在java中绘制面板
我正在编写一个包含许多不同视图的程序。 其中一个是相当图形密集型(它显示一个互连的图形)。 其他人只是展示小而复杂的图表。
我发现主视图的绘制时间很长(甚至只绘制当前可见的区域),并且在绘制时,界面的其余部分变得非常慢。
我的问题是,我可以创建一个新线程来处理绘画 - 如果是这样,它会导致性能提升,我怀疑它不会。 我尝试过以下方法:
创建一个抽象类ThreadPaintablePanel,我的复杂视图继承自。
public abstract class ThreadPaintablePanel extends JPanel{
private Thread painter;
public abstract void paintThread(Graphics g);
protected void callPaintThread(Graphics g){
if(painter != null){
painter.interrupt();
}
painter = new Thread(new PaintRunnable(this, g));
painter.start();
}
}
然后在我复杂的视图中,我的paintComponent方法就是:super.callPaintThread(g);
重写的paintThread方法包含我的所有绘画代码。 然而,这会导致未上漆的面板。 我错过了明显的东西吗?
谢谢
应该在EDT上修改Swing GUI。 为了更好地提供帮助,请发布SSCCE。
你不能让任何线程,但事件发送线程(EDT)触摸GUI。让其他线程弄乱GUI会导致麻烦和异常。您可以使用多线程多缓冲技术。它涉及两个步骤:
为了并行化复杂的绘图例程,您可以简单地将整个"视图"划分为补丁,让一个线程将一个补丁绘制到一个图像中。这是一个使用Java处理图像的教程。
获得图像后,可以覆盖paintComponent并使用Graphics.drawImage方法让EDT显示完整或部分视图,方法是将相应修补的图像拼接在一起。
为了避免不必要的工作,请确保最初执行第一步,然后仅在视图更改后执行,否则只需再次绘制先前计算的结果。此外,如果可以缩小视图内部在帧之间发生更改的区域,请尝试仅更新部分修补程序。
让我们假设您的视图至少与最佳线程数一样高,因此我们可以垂直分区视图。另外,让我们假设绘制任何像素所需的工作量与其他像素相同,因此我们可以为每个补丁使用相同的大小。这两个假设使事情变得容易多了。
代码如下。如果您不需要计算机执行任何其他操作,则可以将nThreads设置为核心数。请注意,代码也使用伪代码"parallel for",这里解释:
// let multiple threads write all patches
public BufferedImage[] writePatches(...)
{
// Given data:
const int nThreads = ...; // the amount of threads that you want
Rectangle viewBox = ...; // The view rectangle
// Immediate data:
Dimension viewSize = viewBox.getSize();
int defaultPatchHeight = (int)ceil((float)viewSize.height / nThreads);
int lastPatchHeight = viewSize.height - (nThreads-1) * defaultPatchHeight;
// The actual"buffer" is a set of images
BufferedImage[] images = new BufferedImage[nThreads];
// ...
// pseudocode for parallel processing of a for loop
parallel-for (nThreads, threadId)
{
// the starting point and size of this thread's patch
// handle boundary (last) patch
int w = viewBox.width;
int h = threadId == nThread-1 ? lastPatchHeight : defaultPatchHeight;
int x = viewBox.x;
int y = viewBox.y + threadId * defaultPatchHeight;
BufferedImage patch = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = off_Image.createGraphics();
// use g to draw to patch image here
// better yet: Re-use existing patches and only update the parts that changed.
images[threadId] = patch;
}
return images;
}
// ...
// override paintComponent
@Override
void paintComponent(Graphics gg)
{
Graphics2D g = (Graphics2D) gg;
// ...
// stitch all images together (you can also just display only some images here)
for (int threadId = 0; threadId < nThreads; ++threadId)
{
int w = viewBox.width;
int h = threadId == nThread-1 ? lastPatchHeight : defaultPatchHeight;
int x = viewBox.x;
int y = viewBox.y + threadId * defaultPatchHeight;
// use pre-computed images here
BufferedImage patch = images[threadId];
g.drawImage(patch, x, y, ...);
}
}
优秀的答案 - 一旦我测试出来,我会将其标记为正确。是否可以通过绘制多个图像然后渲染为一个来提高性能?我问的原因是我对线程的理解(有限)是他们只在需要IO(或其他一些阻塞操作)时才提高性能。为什么渲染图像(基本上是内存操作)符合此要求?
你的问题远远超出了这个主题的范围。您的程序现在受计算限制(或受CPU限制)。最基本的总结:运行多个线程允许您在单个核心上运行速度不够快的问题上投入更多CPU核心。一个线程一次不能在多个核心上运行。当您使所有可用内核饱和的线程数量时,您将获得最大性能。对于通信开销很小的问题,即#threads == #core。
我明白,这就是我认为的情况。谢谢
将2D域(例如整个视图)划分为相同大小的补丁需要一些习惯。另外(正如我刚刚添加到答案中),您需要特别注意边界补丁。
我添加了一些代码来解释一些数学
@ZackNewsham如果这是问题的解决方案,你介意我编辑你的问题以使它更通用吗?
随意编辑问题 - 它肯定似乎是一个解决方案(我还没有尝试并行部分),它似乎还没有提供性能提升(我认为这种方法允许使用显卡?)但我遇到的问题是,我必须阻止直到绘制整个图像,或者绘制的图像不完整,我确实调查了updateImage方法,但它永远不会被调用。
很好的答案。只是想补充说补丁不需要大小相同 - 选择有意义的东西。如果EDT非常忙于其他东西,即使N为1,你也可能看到一些加速。虽然显然N更高(达到极限)更好。
您可以通过在图像全部完成之前不显示任何内容来避免不完整的图像。此外,您可能不希望每帧都重写您的图像,除非您真的必须这样做。您可以通过使用最后一帧中与GUI相关的值来消除阻塞。你可以在不久的将来使用GPU。
@Domi,在图像完成之前你怎么不显示东西?没有举起EDT?
@ZackNewsham只显示以前的结果。 (为方便起见,您可能希望在第一次绘制调用之前生成一次缓冲区。)
awwwww - 男人,我只知道你一直在试图说什么 - 我每次滚动都会重新生成缓冲的图像,因为我每次只画出可见区域,现在我把它画成了整个画面在一开始,每次都有一些变化 - 现在FLIES,真棒,谢谢!
@ZackNewsham你能发布你得到的结果的简短可执行例子吗?我知道你上次在这个帖子中经过了多年,但现在我遇到了同样的问题,并试图在我的java应用程序中增加fps。
我想你想要做的是绘制到非UI线程中的缓冲区(所以你管理的那个),并在完成时(在UI线程中)复制缓冲区。
感谢您的超快速答案 - 虽然我不确定您对缓冲区的绘制是什么意思 - 您能给我一些示例代码,或者只是一些类/方法名称来查找吗?
用java线程绘制图案_关于多线程:使用线程在java中绘制面板相关推荐
- 如何查找历史线程阻塞原因_吊打面试官!Java多线程并发 108 道题,你能答对多少?...
多线程并发108题 1.Java中实现多线程有几种方法 2.继承Thread 类 3.实现Runnable 接口. 4.ExecutorService. Callable. Future 有返回值线程 ...
- 线程同步,线程不同步_同步多线程集成测试
线程同步,线程不同步 测试线程非常困难,这使得为被测多线程系统编写良好的集成测试非常困难. 这是因为在JUnit中,测试代码,被测对象和任何线程之间没有内置的同步. 这意味着,当您必须为创建并运行线程 ...
- java线程池案例_使用Executors 和 ThreadPoolExecutor实现Java线程池案例
并发主题 使用Executors 和 ThreadPoolExecutor实现Java线程池案例 首先需要一个工作线程: package com.journaldev.threadpool; publ ...
- java三个线程 顺序执行_如何确保三个线程顺序执行
三个线程t1.t2.t3.确保三个线程,t1执行完后t2执行,t2执行完后t3执行. 一.使用join thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程. ...
- hystrix 源码 线程池隔离_“池”的思想:从java线程池到数据库连接池的源码解读(1)...
一. java线程池 带着问题: 线程是什么时候被创建的? 线程会一直循环取任务任务吗?怎么做的? 线程取不到任务会怎么样? 线程会被Runnable和Callable的异常干掉吗? 线程怎么干掉自己 ...
- java有关的论述_中国大学MOOC: 以下有关JAVA线程的论述,正确的是()。
中国大学MOOC: 以下有关JAVA线程的论述,正确的是(). 答:Java 线程由JAVA虚拟机JVM管理 Java 线程创建有两种方法:1)扩展java.lang.Thread类:2)实现Runn ...
- 中秋节图案 用java代码打出来_这个中秋,我用 Java 画了一个月饼!
栈长代表微信公众号 "Java技术栈" 祝所有粉丝中秋佳节快乐! 为了用一种特殊的方式表达我的心意,去年中秋节,我写了这篇文章: 没错,去年一天,我学了 20 种编程语言,刺激.. ...
- 西工大java高级网络编程_西工大16春《JAVA高级网络编程》平时作业
西工大16春<JAVA高级网络编程>平时作业 7 o& [9 w ^# D Z一.单选题:[25道,总分:100分]5 z# ?* Z! M% M1 h4 R# n. D+ a ...
- java网络爬虫论文_毕业设计(论文)-基于JAVA的网络爬虫的设计与实现.doc
您所在位置:网站首页 > 海量文档  > 计算机 > Java 毕业设计(论文)-基于JAVA的网络爬虫的设计与实现. ...
最新文章
- 引入 ServletContextListener @Autowired null 解决办法
- 图解Detours实例
- C语言使用array实现stack(附完整源码)
- Unity 2017 Game Optimization 读书笔记 Dynamic Graphics(1)
- linux原有的文件系统扩展,原来linux不用LVM也能扩展文件系统
- @Autowired和@Resource
- 批量文件中加前缀、word删除空白行、删除含有某一个首字母的行
- IT技术人同献爱心行动倡议书
- 阿里云语音合成1.0版
- 个人晋升演讲ppt_晋升面试ppt自我展示演讲稿
- [转]如何进行人脉管理
- oracle表级附加日志视图,Oracle 附加日志(supplemental log)
- 《黑马程序员》 正则的匹配 切割 替换 获取的操作演示
- 基于51单片机的火焰报警器
- PC epub阅读器推荐
- 模拟病人排队看病过程c语言,模拟病人到医院排队看病上机内容完整实验报告.doc...
- 乐视网:贾跃亭解质押150万股股票系法院司法执行操作
- 小榕SQL注入工具使用
- Android实现箭头无限循环上升的简单动画
- 兄弟一体机硒鼓清零7195 7500 7530DN 7895DW 7700D B7720硒鼓清零方法