亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

多線程(即基于線程池)Java 應用程序中的損壞結果

多線程(即基于線程池)Java 應用程序中的損壞結果

絕地無雙 2023-09-27 16:24:21
我正在嘗試 Java 中的多線程,更具體地說,是線程池。作為測試,我編寫了一個應用程序,該應用程序僅使用多線程來更改圖像的顏色以提高速度。然而,由于某種我不知道的原因,根據我如何設置此測試,我得到的結果已損壞。下面我將描述測試應用程序如何與完整的源代碼一起工作。非常歡迎任何幫助!謝謝你!測試應用我有一個 400x300 像素的圖像緩沖區,用深藍色初始化,如下所示:程序必須用紅色完全填充它。盡管我可以簡單地循環所有像素,并按順序將每個像素著色為紅色,但為了提高性能,我決定利用并行性。因此,我決定用單獨的線程填充每個圖像行。由于行數(300 行)比可用 CPU 核心數大得多,因此我創建了一個線程池(包含 4 個線程),它將消耗 300 個任務(每個任務負責填充一行)。該計劃的組織如下:RGB 類:將像素顏色保存在雙精度數 3 元組中。RenderTask 類:用紅色填充圖像緩沖區的給定行。渲染器類:創建圖像緩沖區。使用“newFixedThreadPool”創建線程池。創建 300 個任務供線程池使用。完成線程池服務。將圖像緩沖區寫入 PPM 文件。一切似乎都適用于該代碼,并且我得到了預期的紅色圖像緩沖區,如下所示:問題但是,如果我修改 RenderTask.run() 方法,使其按順序多次重復設置同一緩沖區位置的顏色,如下所示(我將其稱為Version 2):    @Override    public void run() {           for(int column = 0; column < row_width; ++column) {            for(int s = 0; s < 256; ++s) {                image_buffer[current_row][column] =  new RGB(1.0, 0.0, 0.0);            }        }    }然后我得到以下損壞的圖像緩沖區:實際上,每次運行程序的結果都不同,但總是損壞。據我了解,沒有兩個線程同時寫入同一內存位置,因此似乎沒有出現競爭情況。即使在我認為不會發生的“錯誤共享”的情況下,我也期望只會降低性能,而不是損壞結果。因此,即使有冗余的分配,我也希望得到正確的結果(即完全紅色的圖像緩沖區)。所以,我的問題是:如果程序的版本 2 與版本 1 的唯一區別是賦值操作在線程范圍內冗余執行,為什么會發生這種情況?是否會出現某些線程在完成之前就被銷毀的情況?這會是 JVM 中的錯誤嗎?或者我錯過了一些微不足道的事情?(最有力的假設:)感謝你們!!
查看完整描述

2 回答

?
撒科打諢

TA貢獻1934條經驗 獲得超2個贊

ExecutorService.shutdown() 不會等待其所擁有的任務終止,它只會停止接受新任務。

調用 shutdown 后,如果您想等待執行程序服務完成,則應該在執行程序服務上調用 waitTermination。

因此,當您開始將圖像寫入文件時,所有任務尚未完成執行。


查看完整回答
反對 回復 2023-09-27
?
寶慕林4294392

TA貢獻2021條經驗 獲得超8個贊

要添加答案,您可以使用以下代碼來關閉線程池


以下方法分兩個階段關閉 ExecutorService,首先調用 shutdown 拒絕傳入任務,然后調用 shutdownNow(如有必要)取消任何延遲任務:


void shutdownAndAwaitTermination(ExecutorService pool) {

? pool.shutdown(); // Disable new tasks from being submitted

? try {

? ? // Wait a while for existing tasks to terminate

? ? if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {

? ? ? pool.shutdownNow(); // Cancel currently executing tasks

? ? ? // Wait a while for tasks to respond to being cancelled

? ? ? if (!pool.awaitTermination(60, TimeUnit.SECONDS))

? ? ? ? ? System.err.println("Pool did not terminate");

? ? }

? } catch (InterruptedException ie) {

? ? // (Re-)Cancel if current thread also interrupted

? ? pool.shutdownNow();

? ? // Preserve interrupt status

? ? Thread.currentThread().interrupt();

? }

}


查看完整回答
反對 回復 2023-09-27
  • 2 回答
  • 0 關注
  • 101 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號