java - 同步线程池ExecutorService

标签 java multithreading synchronization threadpool

这是我第一次使用线程池,我不太了解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关闭和任务执行/排空工作队列/从工作队列中取出是一件很容易的事。因此,您不能依赖线程中断机制或其他方法。您所能保证的是:

Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.

This method does not wait for previously submitted tasks to complete execution.



为了更深入地了解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值提供的排序。此处的ctlAtomicInteger内部存储的全局池状态(用于非阻塞原子ThreadPoolExecutor状态获取)。

因此,以下情况是可能的。
  • 称为getTask的工作线程
  • worker 线程获取池的运行状态。它仍然是RUNNING
  • 另一个线程启动了订单关闭操作,并相应地修改了ctl
  • Worker线程已经从工作队列中接收了一项任务。
  • 关于java - 同步线程池ExecutorService,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51125927/

    相关文章:

    mysql 导入/导出

    java - 循环卡牌游戏

    c# - 从多个线程在字典中添加新项目

    c - 使用 mutex_destroy() 时如何释放内存 : Posix multithreading

    java - 有多少个线程可以同时调用一个对象的非同步方法?

    Spring 交易TransactionSynchronizationManager : isActualTransactionActive vs isSynchronizationActive

    java - 环球音乐播放器说加载媒体时出错

    java - 如何用Java2D绘制内线

    java - 如何为 web 应用程序创建客户端通知服务或者我应该使用观察者模式?

    python - Python 2.7 脚本中的多个 SSH 连接 - 多处理与线程