我有一项长期的任务,就是创建一个位图并保存它,然后重新创建更多的位图,这是我在一个后台线程上做的

ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());
executor.execute(() -> {...bitmap work ...}

但是处理所有位图需要很长时间,所以我创建了一个线程池来使用多线程来加速任务.

private final int cores = Runtime.getRuntime().availableProcessors();
private final ExecutorService executor = Executors.newFixedThreadPool(cores + 1);
for (int i = 0; i < totalPage; i++) {    
    Runnable runnable = () -> {...bitmap work ...}
    executor.submit(runnable);
}

但每当我使用超过1个线程时,它就会在某个任务上随机卡住(比如127个线程中有7个),没有错误或任何它无法处理的任务.我可以在executor队列中查看挂起的任务.但是,如果我将线程池更改为使用1个线程,它可以毫无问题地工作并处理所有任务.

下面是完整的实际代码

ExecutorService executor = Executors.newFixedThreadPool(cores + 1);
        List<Future<?>> futureList = new ArrayList<>();
        boolean allDone = false;

        try {
            //Convert pdf to Bitmap
            ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.open(new File(pdfFileName), ParcelFileDescriptor.MODE_READ_ONLY);
            PdfRenderer pdfRenderer = new PdfRenderer(parcelFileDescriptor);
            int totalPage = pdfRenderer.getPageCount();

            final int[] counter = {1};
            for (int i = 0; i < totalPage; i++) {
                int finalI = i;
                String finalOriginalPdfName = originalPdfName;
                String finalGeneratedPdfName = generatedPdfName;
                Runnable runnable = () -> {
                    //pd.setMessage("Processing page " + (finalI + 1) + " of " + totalPage);
                    PdfRenderer.Page page = pdfRenderer.openPage(finalI);

                    Bitmap pageBitmap = Bitmap.createBitmap((300 * page.getWidth()) / 72, (300 * page.getHeight()) / 72, Bitmap.Config.ARGB_8888);
                    Canvas canvas = new Canvas(pageBitmap);
                    canvas.drawColor(Color.WHITE);
                    canvas.drawBitmap(pageBitmap, 0, 0, null);
                    page.render(pageBitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
                    page.close();


                    //Crop bitmaps and temporarily store on app data directory

                    for (int k = 0; k < SlipBoundingBox.Y.length; k++) {
                        for (int j = 0; j < SlipBoundingBox.X.length; j++) {
                            Bitmap slipBitmap = Bitmap.createBitmap(pageBitmap, SlipBoundingBox.X[j], SlipBoundingBox.Y[k], SlipBoundingBox.WIDTH, SlipBoundingBox.HEIGHT);
                            //Filename formation originalPdfName_generatePdfName_pdfPageIndex_x_y.extension
                            File slip = new File(
                                    getExternalFilesDir("slips")
                                            + "/"
                                            + finalOriginalPdfName
                                            + "_"
                                            + finalGeneratedPdfName
                                            + "_"
                                            + finalI +
                                            "_"
                                            + SlipBoundingBox.X[j]
                                            + "_"
                                            + SlipBoundingBox.Y[k]
                                            + "_.jpg");
                            try (FileOutputStream out1 = new FileOutputStream(slip)) {
                                slipBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out1);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            slipBitmap.recycle();
                        }
                    }
                    pageBitmap.recycle();
                    pd.setMessage("Processed " + counter[0] + " of " + totalPage + " pages");
                    counter[0]++;
                };
                Future<?> future = executor.submit(runnable);
                Log.d(TAG, "processPdf: " + future.isDone());
                futureList.add(future);

            }
            //Todo close pdfrender on all page processed
            //pdfRenderer.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

推荐答案

原来问题是我在回收位图之前关闭了pdf页面.

page.close();
.....
pageBitmap.recycle();

我移动了page.close()后,回收位图和线程不再挂起

pageBitmap.recycle();
page.close();

Java相关问答推荐

Annotation @ Memphier无法正常工作,并表示:class需要一个bean,但找到了2个bean:

如何粘合(合并)文件Lucene?

CompleteableFuture是否运行在不同的内核上?

SpringBoot+Java 17@Valid未验证POJO

暂停计时器

测试容器无法加载类路径初始化脚本

如何在EXCEL单元格中添加形状和文本

在Java中将int[]矩阵添加到ArrayList中,但出现错误

Java SSLKeyManager出厂密码

错误:未找到扩展元素在JBossEAP 7.2中安装FUSE时出错

组合连接以从两个表返回数据

嘲笑黄瓜中的对象

如何对存储为字符串的大数字数组进行排序?

协同 routine 似乎并不比JVM线程占用更少的资源

H2数据库仅支持%1个结果集?

如果c不为null,Arrays.sort(T[]a,Comparator<;?super T>;c)是否会引发ClassCastException?

如何使用外部函数从Java中获取C++ struct 的返回值&;内存API

设置背景时缺少Android编辑文本下划线

如何从指定某些字段的父对象创建子对象

将Optionals/null安全添加到嵌套的flatMap/流