您的当前位置:首页正文

ThreadPoolExecutor submit和execute方法的区别

2024-11-24 来源:个人技术集锦

ThreadPoolExecutor submit和execute方法的区别

结论:

  • execute:

    • 只能提交Runnable接口的对象,我们知道Runnable接口的run方法是没有返回值的。
    • execute方法提交的任务异常是直接抛出的
    • 即线程抛出异常后会重新创建线程
  • submit:

    • 可以提交Runnable也可以提交Callable对象,即可以有返回值,也可以没有
    • submit方法是是捕获了异常的,当调用FutureTask的get方法时,才会抛出异常
    • 即线程抛出异常后不会重新创建线程,会重用

submit 中 的run方法

//FutureTask.java
public void run() {
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                setException(ex);
            }
            if (ran)
                set(result);
        }
    } finally {
        // runner must be non-null until state is settled to
        // prevent concurrent calls to run()
        runner = null;
        // state must be re-read after nulling runner to prevent
        // leaked interrupts
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}

可以看到 异常被放到 FutureTask 中 ,只有在 调用 get 方法的时候才会被抛出

而 execute 方法,就直接抛出异常,并且线程直接kill :

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);
    }
}

测试线程是否死亡

execute:

public static void main(String[] args) {
    ExecutorService service = Executors.newFixedThreadPool(2);
    service.submit(()->{
        System.out.println("thread: "+ Thread.currentThread().getName());
        if (1==1){
            throw new RuntimeException("异常");
        }
    });
    service.submit(()->{

        System.out.println("thread: "+ Thread.currentThread().getName());
        if (1==1){
            throw new RuntimeException("异常");
        }
    });
    service.submit(()->{
        System.out.println("thread: "+ Thread.currentThread().getName());
        if (1==1){
            throw new RuntimeException("异常");
        }
    });

}

结果:

thread: pool-1-thread-1
thread: pool-1-thread-2
thread: pool-1-thread-2

submit:

public static void main(String[] args) {
    ExecutorService service = Executors.newFixedThreadPool(2);
    service.execute(()->{
        System.out.println("thread: "+ Thread.currentThread().getName());
        if (1==1){
            throw new RuntimeException("异常");
        }
    });
    service.execute(()->{

        System.out.println("thread: "+ Thread.currentThread().getName());
        if (1==1){
            throw new RuntimeException("异常");
        }
    });
    service.execute(()->{
        System.out.println("thread: "+ Thread.currentThread().getName());
        if (1==1){
            throw new RuntimeException("异常");
        }
    });

}

结果:

thread: pool-1-thread-1
thread: pool-1-thread-2
thread: pool-1-thread-3
Exception in thread "pool-1-thread-1" 
	Exception in thread "pool-1-thread-2" Exception in thread "pool-1-thread-3" java.lang.RuntimeException: 异常
at com.icmp.agenda.util.LocalDateTimeUtil.lambda$main$2(LocalDateTimeUtil.java:44)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
java.lang.RuntimeException: 异常
at com.icmp.agenda.util.LocalDateTimeUtil.lambda$main$0(LocalDateTimeUtil.java:31)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
java.lang.RuntimeException: 异常
at com.icmp.agenda.util.LocalDateTimeUtil.lambda$main$1(LocalDateTimeUtil.java:38)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
显示全文