精华内容
下载资源
问答
  • 线程池中的execute方法大家都不陌生,即开启线程执行池中的任务。还有一个方法submit也可以做到,它的功能是提交指定的任务去执行并且返回Future对象,即执行的结果。下面简要介绍一下两者的三个区别:1、接收的参数...

    线程池中的execute方法大家都不陌生,即开启线程执行池中的任务。

    还有一个方法submit也可以做到,它的功能是提交指定的任务去执行并且返回Future对象,即执行的结果。

    下面简要介绍一下两者的三个区别:

    1、接收的参数不一样

    2、submit有返回值,而execute没有

    用到返回值的例子,比如说我有很多个做validation的task,我希望所有的task执行完,然后每个task告诉我它的执行结果,是成功还是失败,如果是失败,原因是什么。

    然后我就可以把所有失败的原因综合起来发给调用者。

    个人觉得cancel execution这个用处不大,很少有需要去取消执行的。

    而最大的用处应该是第二点。

    3、submit方便Exception处理

    意思就是如果你在你的task里会抛出checked或者unchecked exception,

    而你又希望外面的调用者能够感知这些exception并做出及时的处理,那么就需要用到submit,通过捕获Future.get抛出的异常。

    下面一个小程序演示一下submit方法

    public class RunnableTestMain {

    public static void main(String[] args) {

    ExecutorService pool = Executors.newFixedThreadPool(2);

    /**

    * execute(Runnable x) 没有返回值。可以执行任务,但无法判断任务是否成功完成。

    */

    pool.execute(new RunnableTest("Task1"));

    /**

    * submit(Runnable x) 返回一个future。可以用这个future来判断任务是否成功完成。请看下面:

    */

    Future future = pool.submit(new RunnableTest("Task2"));

    try {

    if(future.get()==null){//如果Future's get返回null,任务完成

    System.out.println("任务完成");

    }

    } catch (InterruptedException e) {

    } catch (ExecutionException e) {

    //否则我们可以看看任务失败的原因是什么

    System.out.println(e.getCause().getMessage());

    }

    }

    }

    public class RunnableTest implements Runnable {

    private String taskName;

    public RunnableTest(final String taskName) {

    this.taskName = taskName;

    }

    @Override

    public void run() {

    System.out.println("Inside "+taskName);

    throw new RuntimeException("RuntimeException from inside " + taskName);

    }

    }

    展开全文
  • execute和submit的区别 方法 使用场景 是否有返回值 异常处理 execute 适用于不需要返回值的场景 无 线程内部如果发生异常,主线程无感知。异常会通过stdout方式显示,如果需要在日志中打印,需要单独设置。...

    execute和submit的区别

    方法 使用场景 是否有返回值 异常处理
    execute 适用于不需要返回值的场景 线程内部如果发生异常,主线程无感知。异常会通过stdout方式显示,如果需要在日志中打印,需要单独设置。方法见示例3
    submit 适用于需要获取返回值的场景 调用future get方法时,异常会抛出。如果不调用get方法,则无法获取。

    示例1:execute使用

      private static void executeDemo() {
        Runnable runnable = ()-> {
          System.out.println("thread execute");
        };
    
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.execute(runnable);
    
        executorService.shutdown();
      }
    

    输出:

    thread execute
    

    示例2:submit使用

      private static void submitDemo() throws Exception {
        Callable<String> call = ()-> {
          System.out.println("thread submit");
          return "hello";
        };
    
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<String> future = executorService.submit(call);
    
        String output = future.get();
    
        System.out.println("output : " + output);
        executorService.shutdown();
      }
    

    输出:

    thread submit
    output : hello
    

    示例3:execute,线程内部抛出异常,并打印出相关结果

      private static void executeException2Demo() {
        Runnable runnable = ()-> {
          System.out.println("thread execute before exception");
          throw new RuntimeException("test exception");
        };
    
        ThreadFactory threadFactory = r -> {
          Thread thread = Executors.defaultThreadFactory().newThread(r);
          thread.setUncaughtExceptionHandler((t,e) -> {
            System.err.println("catch exception for execute : " + e.getMessage());
          });
          return thread;
        };
    
        ExecutorService executorService = Executors.newFixedThreadPool(2, threadFactory);
        executorService.execute(runnable);
    
        executorService.shutdown();
      }
    

    输出:

    thread execute before exception
    catch exception for execute : test exception
    

    备注:
    如果需要捕获excute时的异常,需要通过线程的setUncaughtExceptionHandler方法来设置。

    示例4: submit,线程内部抛出异常,并打印出相关结果

      private static void submitExecptionDemo() throws Exception {
        Callable<String> call = ()-> {
          System.out.println("thread submit before exception");
          throw new RuntimeException("test submit exception");
        };
    
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<String> future = executorService.submit(call);
    
        try {
          String output = future.get();
    
          System.out.println("output : " + output);
        } catch (Exception e) {
          System.err.println("catch exception:" + e.getMessage());
        }
    
        executorService.shutdown();
      }
    

    输出:

    thread submit before exception
    catch exception:java.lang.RuntimeException: test submit exception
    

    备注:

    1. 异常是调用get方法时抛出的。
    2. 没有调用get方法时,即使线程已经允许完了,异常也不会抛出。
    展开全文
  • Java线程池execute()方法源码解析

    万次阅读 2017-09-23 12:41:15
    先看作者给出的注释来理解线程池到底有什么作用 * Thread pools address two different problems: they usually* provide improved performance when executing large numbers of* asynchronous tasks, due to ...

    先看作者给出的注释来理解线程池到底有什么作用

    * Thread pools address two different problems: they usually
    * provide improved performance when executing large numbers of
    * asynchronous tasks, due to reduced per-task invocation overhead,
    * and they provide a means of bounding and managing the resources,
    * including threads, consumed when executing a collection of tasks.
    * Each {
    @code ThreadPoolExecutor} also maintains some basic
    * statistics, such as the number of completed tasks.

    线程池处理了两个不同的问题,线程池通过减少线程正式调用之前的开销来给大量异步任务更优秀的表现,与此同时给出了一系列绑定管理任务线程的一种手段。每个线程池都包含了一些基本信息,比如内部完成的任务数量。

     

    让我们先看ThreadPoolExecutor类的一系列代表状态的

    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    private static final int COUNT_BITS = Integer.SIZE - 3;
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
    
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;
    
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    private static int ctlOf(int rs, int wc) { return rs | wc; }

     

    ctl作为AtomicInteger类存放了类中的两种信息,在其中由高3位来保存线程池的状态,后29位来保存此时线程池中的Woker类线程数量(由此可知,线程池中的线程数量最高可以接受大约在五亿左右)。由此可见给出的runStateOf()和workerCountOf()方法分别给出了查看线程状态和线程数量的方法。

    该类一共给出了五种状态,让我们看作者给出的注释,

    *   RUNNING:  Accept new tasks and process queued tasks
    *   SHUTDOWN: Don't accept new tasks, but process queued tasks
    *   STOP:     Don't accept new tasks, don't process queued tasks,
    *             and interrupt in-progress tasks
    *   TIDYING:  All tasks have terminated, workerCount is zero,
    *             the thread transitioning to state TIDYING
    *             will run the terminated() hook method
    *   TERMINATED: terminated() has completed

    RUNNING状态可以接受新进来的任务,同时也会执行队列里的任务。

    SHUTDOWN 状态已经不会再接受新任务,但仍旧会处理队列中的任务。

    STOP状态在之前的基础上,不会处理队列中的人物,在执行的任务也会直接被打断。

    TIDYING状态在之前的基础上,所有任务都已经终止,池中的Worker线程都已经为0,也就是stop状态在清理完所有工作线程之后就会进入该状态,同时在shutdown状态在队列空以及工作线程清理完毕之后也会直接进入这个阶段,这一阶段会循环执行terminated()方法。

    TERMINATED 状态作为最后的状态,在之前的基础上terminated()方法也业已执行完毕,才会从上个状态进入这个状态,代表线程池已经完全停止。

     

    由于线程池的状态都是通过AtomicInteger来保存的,可以通过比较的方式简单的得到当前线程状态。

     

     

     

    private final BlockingQueue<Runnable> workQueue;
    
    private final ReentrantLock mainLock = new ReentrantLock();
    
    private final HashSet<Worker> workers = new HashSet<Worker>();
    
    private final Condition termination = mainLock.newCondition();
    
    private int largestPoolSize;
    
    private long completedTaskCount;
    
    private volatile ThreadFactory threadFactory;
    
    private volatile RejectedExecutionHandler handler;
    
    private volatile long keepAliveTime;
    
    private volatile boolean allowCoreThreadTimeOut;
    
    private volatile int corePoolSize;
    
    private volatile int maximumPoolSize;

     

     

     

    接下来是线程池的几个有关工作线程的变量

    corePoolSize表示线程池中允许存活最少的工作线程数量,但值得注意的是如果allowCoreThreadTimeOut一旦设置true(默认false),每个线程的存活时间只有keepAliveTime也就是说在allowCoreThreadTimeOut为true的时候,该线程池最小的工作线程数量为0;maximumPoolSize代表线程池中最大的工作线程数量。

    keepAliveTime为线程池中工作线程数量大于corePoolSize时,每个工作线程的在等待工作时最长的等待时间。

    workQueue作为线程池的任务等待队列,这个将在接下来的execute()里详细解释。

    Workers作为存放线程池中存放工作线程的容器。

    largestPoolSize用来记录线程池中存在过的最大的工作线程数量。

    completedTaskCount用来记录线程池完成的任务的总数。

    Handler作为线程池中在不能接受任务的时候的拒绝策略,我们可以实现自己的拒绝策略,在实现了RejectedExecutionHandler接口的前提下。下面是线程池的默认拒绝策略,

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() +
                                             " rejected from " +
                                             e.toString());
    }

    threadFactory作为线程池生产线程的工厂类,下面是线程池默认的线程工厂的生产线程方法。

    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r,
                              namePrefix + threadNumber.getAndIncrement(),
                              0);
        if (t.isDaemon())
            t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }

     

    我们可以先看我们最常调用的execute()方法。

     

     

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
     
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }

     

    execute()内部的调用逻辑非常清晰。

    如果当前线程池的工作线程数量小于corePoolSize,那么直接调用addWoker(),来添加工作线程。下面是addWorker()的具体方法

     

    private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;
    
            for (;;) {
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
            }
        }
    
        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            final ReentrantLock mainLock = this.mainLock;
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                mainLock.lock();
                try {
                    int c = ctl.get();
                    int rs = runStateOf(c);
    
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive())                         
    		   throw new IllegalThreadStateException();
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

     

    这段方法比较长,但整体的逻辑还是清晰的。

     

    首先判断当前线程池的状态如果已经状态不是shutdown或者running,或者已经为shutdown但是工作队列已经为空,那么这个时候直接返回添加工作失败。接下来是对线程池线程数量的判断,根据调用时的core的值来判断是跟corePoolSize还是 maximumPoolSize判断。

    在确认了线程池状态以及线程池中工作线程数量之后才真正开始添加工作线程

    新建立一个worker类(线程池的内部类,具体的工作线程),将要执行的具体线程做为构造方法中的参数传递进去,接下来将其加入线程池的工作线程容器workers,并且更新工作线程最大量,最后调用worker工作线程的start()方法就完成了工作线程的建立与启动

     

    让我们回到execute()方法,如果我们在一开始的线程数量就大于corePoolSize或者我们在调用addworker()方法的过程中出现了问题导致添加工作线程数量失败,那么我们会继续执行接下来的逻辑。

    在判断完毕线程池的状态后则会将任务通过workQueue.offer())方法试图加进任务队列。Offer()方法的具体实现会根据在线程池构造方法中选取的任务队列种类而产生变化

    但是如果成功加入了任务队列仍旧需要注意判断如果线程池的状态如果已经不是running那么会拒绝执行这一任务并执行相应的拒绝策略。在最后需要记得成功加入队列成功后如果线程池中如果已经没有了工作线程,需要重新建立一个工作线程去执行仍旧在任务队列中等待执行的任务。

    如果在之前的前提下加入任务队列也失败了(比如任务队列已满),则会在不超过线程池最大线程数量的前提下建立一个工作线程来处理

    如果在最后的建立工作线程也失败了那么我们只有很遗憾的执行任务的拒绝策略了

     

    在之前的过程中我们建立了工作线程Worker()类,那么我们现在看看worker类的内部实现,也可以说是线程池的核心部分。Worker类作为线程池的内部类,接下来是Worker()类的成员。

    final Thread thread;
    
    Runnable firstTask;
    
    volatile long completedTasks;

     

    thread作为worker的工作线程空间,由线程池中所设置的线程工厂生成。

     

    firstTask则是worker在构造方法中所接受到的所要执行的任务。

    completedTasks作为该worker类所执行完毕的任务总数。

     

    接下来我们可以看最重要的也就是我们之前建立完Worker类之后立马调用的run()方法了

    public void run() {
        runWorker(this);
    }

    run()方法实现的很简单我们可以继续追踪下去

    final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); 
        boolean completedAbruptly = true;
        try {
            while (task != null || (task = getTask()) != null) {
                w.lock();
                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);
        }
    }

     

    如果这个worker还没有执行过在构造方法就传入的任务那么在这个方法中会直接执行这一任务,如果没有,则会尝试去从任务队列当中去取的新的任务。

     

    但是在真正调用任务之前仍旧会判断线程池的状态如果已经不是running亦或是shutdwon,则会直接确保线程被中断如果没有将会继续执行并确保不被中断

    接下来可见我们所需要的任务直接在工作线程中直接以run()方式以非线程的方式所调用,这里也就是我们所需要的任务真正执行的地方。

    在执行完毕后工作线程的使命并没有真正宣告段落while部分worker仍旧会通过getTask()方法试图取得新的任务下面是getTask()的实现

    private Runnable getTask() {
        boolean timedOut = false; 
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);
    
                   if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }
    
            boolean timed;            
            for (;;) {
                int wc = workerCountOf(c);
                timed = allowCoreThreadTimeOut || wc > corePoolSize;
    
                if (wc <= maximumPoolSize && ! (timedOut && timed))
                    break;
                if (compareAndDecrementWorkerCount(c))
                    return null;
                c = ctl.get();  
                if (runStateOf(c) != rs)
                    continue retry;
            }
    
            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

     

     

    首先仍旧会判断线程池的状态是否是running还是shutdown以及stop状态下队列是否仍旧有需要等待执行的任务。如果状态没有问题,则会跟据allowCoreThreadTimeOutcorePoolSize的值通过对前面这两个属性解释的方式来选择从任务队列中获得任务的方式(是否设置timeout)。其中的timedOut保证了确认前一次试图取任务时超时发生的记录以确保工作线程的回收

     

     

    在runWorker()方法的最后调用了processWorkerExist()方法来执行工作线程的回收

    private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly) 
            decrementWorkerCount();
    
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += w.completedTasks;
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }
    
        tryTerminate();
    
        int c = ctl.get();
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return; 
            }
            addWorker(null, false);
        }
    }

    在这一方法中,首先确保已经重新更新了线程池中工作线程的数量,之后从线程池中的工作线程容器移去当前工作线程,并且将完成的任务总数加到线程池的任务总数当中。

    在最后仍旧要确保线程池中依旧存在大于等于最小线程数量的工作线程数量存在如果没有则重新建立工作线程去等待处理任务队列中任务

     

     

     

     

     

     

     

    展开全文
  • java 线程池execute 和 submit 方法的区别

    ThreadPoolExecutor UML类图

    在这里插入图片描述

    execute 方法定义

    public interface Executor {
        void execute(Runnable command);
    }
    

    submit 方法定义

    public interface ExecutorService extends Executor {
    	<T> Future<T> submit(Callable<T> task);
    
    	<T> Future<T> submit(Runnable task, T result);
    	
    	Future<?> submit(Runnable task);
    }
    

    submit 方法具体实现

    public abstract class AbstractExecutorService implements ExecutorService {
    	public Future<?> submit(Runnable task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<Void> ftask = newTaskFor(task, null);
            execute(ftask);
            return ftask;
        }
        
    	public <T> Future<T> submit(Runnable task, T result) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<T> ftask = newTaskFor(task, result);
            execute(ftask);
            return ftask;
        }
    	
    	public <T> Future<T> submit(Callable<T> task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<T> ftask = newTaskFor(task);
            execute(ftask);
            return ftask;
        }
    }
    

    execute 方法具体实现

    public class ThreadPoolExecutor extends AbstractExecutorService {
    	public void execute(Runnable command) {
    		// 具体实现
    	}
    }
    

    程序验证

    public class ExecuteVsSubmit {
        public static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    
        // 线程池核心线程最大线程数
        private static final int MAX_THREAD_SIZE = 10;
    
        public static void main(String[] args) throws Exception {
            // 模拟请求列表
            List<String> requests = Lists.newArrayList("A0001", "A0002", "A0003", "A0004", "A0005", "B0001", "B0002", "B0003", "B0004", "B0005");
            ExecutorService executor = Executors.newFixedThreadPool(requests.size() > MAX_THREAD_SIZE ? MAX_THREAD_SIZE : requests.size());
    
            // 只在 submit 方式-2 和 submit 方式-3 中用到
            List<Future<Response>> futures = new ArrayList<>();
    
            System.out.println(SDF.format(new Date()) + " 发送请求~~~");
    
            for (String request : requests) {
                // execute 方式 (第二个参数意义不大, 可以参考 `submit 方式-2-2` 的调用方式)
    //            executor.execute(new TaskRunnable(request, new Response()));
    
                // submit 方式-1 (第二个参数意义不大, 可以参考 `submit 方式-2-2` 的调用方式)
    //            executor.submit(new TaskRunnable(request, new Response()));
    
                // submit 方式-2-1
    //            Response response = new Response();
    //            Future<Response> future = executor.submit(new TaskRunnable(request, response), response);
    //            futures.add(future);
    
                // submit 方式-2-2
                Response response = new Response();
                Future<Response> future = executor.submit(() -> {
                    System.out.println(String.format("%s 异步请求接口=[%s]",
                            ExecuteVsSubmit.SDF.format(new Date()), request));
    
                    try {
                        Thread.sleep(5 * 1000);
                        response.setMsg(request);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }, response);
                futures.add(future);
    
                // submit 方式-3
    //            Future<Response> future = executor.submit(new TaskCallable(request));
    //            futures.add(future);
            }
    
    
            // 获取异步结果
            for (Future<Response> future : futures) {
                System.out.println(SDF.format(new Date()) + " 结果=" + future.get().getMsg());
            }
    
            executor.shutdown();
        }
    
    }
    
    
    class TaskCallable implements Callable<Response> {
        private String request;
    
        public TaskCallable(String request) {
            this.request = request;
        }
    
        @Override
        public Response call() throws Exception {
            System.out.println(String.format("%s 异步请求接口=[%s]",
                    ExecuteVsSubmit.SDF.format(new Date()), this.request));
    
            try {
                Thread.sleep(5 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            return new Response(request);
        }
    }
    
    class TaskRunnable implements Runnable {
        private String request;
        private Response response;
    
        public TaskRunnable(String request, Response response) {
            this.request = request;
            this.response = response;
        }
    
        @Override
        public void run() {
            System.out.println(String.format("%s 异步请求接口=[%s]",
                    ExecuteVsSubmit.SDF.format(new Date()), this.request));
    
            try {
                Thread.sleep(5 * 1000);
                response.setMsg(request);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    class Response {
        private String msg;
    }
    
    • execute和submit都属于线程池的方法,execute只能提交Runnable类型的任务,而submit既能提交Runnable类型任务也能提交Callable类型任务。
    • execute会直接抛出任务执行时的异常,submit会吃掉异常,可通过Future的get方法将任务执行时的异常重新抛出。
    • execute所属顶层接口是Executor,submit所属顶层接口是ExecutorService,实现类ThreadPoolExecutor重写了execute方法,抽象类AbstractExecutorService重写了submit方法。
    展开全文
  • } submit内部调用execute submit有返回值 submit方便exception处理 submit的demo: importjava.util.ArrayList;importjava.util.List;importjava.util.Random;importjava.util.concurrent.Callable;importjava.util....
  • 在使用线程池时,我们都知道线程池有两种提交任务的方式,那么他们有什么区别呢?1.execute提交的是Runnable类型的任务,而submit提交的是Callable或者Runnable类型的任务2.execute的提交没有返回值,而submit的提交...
  • Java线程池异常处理在使用ThreadPoolExecutor进行submit提交任务时,有的任务抛出了异常,但是线程池并没有进行提示,即线程池把任务中的异常给吃掉了,可以把submit提交改为execute执行,也可以对ThreadPoolExecutor...
  • java线程池

    2014-06-10 22:11:00
    java线程池 execute(Runnable command):履行Ruannable类型的任务 submit(task):可用来提交Callable或Runnable任务,并返回代表此任务的Future对象 invokeAll(collection of tasks):执行给定的...
  • 本文是线程池execute方法的源码,在此之前可以先看下【线程池的创建】。 ThreadPoolExecutor中execute方法 newCachedThreadPool、newFixedThreadPool、newSingleThreadExecutor的execute方法在ThreadPoolExecutor...
  • Java线程池ThreadPoolExecutor的使用ThreadPoolExecutor就是我们用来实现线程的一个执行器,它实现了Excutor和ExecutorService接口。Excutor接口只定义了一个方法就是execute用来执行任务。ExecutorService继承于...
  • Java:1.8 前言 线程池之前知是知道,但是印象不是很深刻,今天看了下源码,发现源码很好理解,所以记录下; 线程池 要了解线程池,首先要了解线程池里面的状态控制变量ctl。 线程池的ctl是一个原子的...
  • 一:submit()方法,可以提供Future <...execute无返回值public void execute(Runnable command) {if (command == null)throw new NullPointerException();//抛掉异常int c = ctl.get();if (workerCo...
  • 前言没有线程池的多线程分享是没有灵魂的,由...使用线程池,他就会为线程从创建到销毁的全过程保驾护航,我们要做的就只是把task进行submit或者execute即可,废话不多说了,接下来我们一点点的揭开线程池的面纱,一...
  • 最近在看《Java并发编程的艺术》回顾线程池的原理和参数的时候发现一个问题,如果 corePoolSize = 0 且 阻塞队列是无界的。线程池将如何工作?...我们先回顾一下书里面描述线程池execute()工作的逻辑:...
  • 转自: ...   Java 线程池submit和execute submit方法: public abstract class AbstractExecutorService implements ExecutorService { protected &lt;T&gt; Ru...
  • ThreadPoolExecutor的execute方法执行流程前言【Java线程池01】Java线程池简介此文中对Java线程池简介,包含线程池相关的几个类的关系等。【Java线程池02】ThreadPoolExecutor类概述此文介绍了ThreadPoolExecutor的...
  • at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java: 617 ) at java.lang.Thread.run(Thread.java: 745) View Code   Runnable和Callable的区别是, (1)Callable规定的方法...
  • 一、线程池执行任务的流程如果线程池工作线程数如果线程池工作线程数>=corePoolSize并且等待队列未满,将task插入等待队列。如果线程池工作流程数>=corePoolSize并且等待队列已...二、execute()原理public vo...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,102
精华内容 440
关键字:

java线程池execute

java 订阅