簡體   English   中英

同步線程池ExecutorService

[英]Synchronization Thread Pool ExecutorService

這是我第一次使用線程池,我不太了解executorservice的工作方式。 我將水印放在圖像上,然后將它們合並到一張空白圖片上。 但是即使我只使用一個線程,它也只會畫一半。

這是我的WorkerThread類

public class WorkerThread implements Runnable {

    BufferedImage source;
    BufferedImage toDraw;
    int x;
    int y;
    BufferedImage target;
    ParallelWatermarkFilter pf;

    public WorkerThread(BufferedImage source, BufferedImage toDraw, int x, int y, BufferedImage target){
        this.source = source;
        this.toDraw = toDraw;
        this.x = x;
        this.y = y;
        this.target = target;
        pf = new ParallelWatermarkFilter(source, 5);
    }

    @Override
    public void run() {
        pf.mergeImages(source, toDraw, x, y, target);
    }
}

這就是我在FilterClass中使用ExecutorService的方式

    public BufferedImage apply(BufferedImage input) {

        ExecutorService threadpool = Executors.newFixedThreadPool(numThreads);

                for (int w = 0; w < imgWidth; w += watermarkWidth) {
      for (int h = 0; h < imgHeight; h += watermarkHeight) {
            Runnable worker = new WorkerThread(input, watermark, w, h, result);
            System.out.println("WIDTH: " + w + "   HEIGHT: " + h);
            threadpool.execute(worker);
      }
    }

    threadpool.shutdown();

線程是否不等到一個線程完成?

ThreadPoolExecutor關機和任務執行/排空工作隊列/從工作隊列中取出是一件ThreadPoolExecutor的事。 因此,您不能依賴線程中斷機制或其他方法。 您所能保證的是:

啟動有序關閉,在該關閉中執行先前提交的任務,但不接受任何新任務。 如果已關閉,則調用不會產生任何其他影響。

此方法不等待先前提交的任務完成執行。

為了更深入地了解ThreadPoolExecutor實現,讓我們看一下主要的執行方法:

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        while (task != null || (task = getTask()) != null) {
            w.lock();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted.  This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);
    }
}

這里的關鍵部分是調用getTask() 其片段是:

 if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
     decrementWorkerCount();
     return null;
 }

該方法不同步,僅依靠CAS'ed ctl值提供的排序。 這里的ctl是存儲在AtomicInteger內部的全局池狀態(用於非阻塞原子ThreadPoolExecutor狀態獲取)。

因此,以下情況是可能的。

  1. 名為getTask工作線程
  2. 輔助線程獲取了池的運行狀態。 它仍在RUNNING
  3. 另一個線程啟動了命令關閉並相應地修改了ctl
  4. 工作線程已經從工作隊列中接了一個任務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM