———— 通常线程池的执行方法有两种execute和submit,那么他们有什么区别呢?
1.接受任务的类型
execute 只能接受Runnable类型的任务
void execute(Runnable command); 复制代码
submit不管是Runnable还是Callable类型的任务都可以接受,但是Runnable返回值均为void,所以使用Future的get()获得的还是null
<T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); 复制代码
2.execute方法适用于那些不需要关注返回值的场景,我们只需要把要执行的任务丢进线程池
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Thread02 { public static void main(String[] args) throws Exception { ExecutorService pool = Executors.newFixedThreadPool(1); pool.execute(() -> { System.out.println("我爱学习,我爱java"); }); } } 复制代码
运行结果
我爱学习,我爱java 复制代码
submit方法适用于需要关注返回值的场景,通常这种的我们在工作中用的比较多,可以通过Future的get()方法得到线程的运行结果
import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Thread02 { public static void main(String[] args) throws Exception { ExecutorService pool = Executors.newFixedThreadPool(1); //我们取一个String类型的返回值 Future<String> future = pool.submit(new Callable<String>() { public String call() throws Exception { return "我爱java"; } }); String result = future.get(); System.out.println("线程的运行结果为: " + result); //我们取一个boolean类型的返回值 Future<Boolean> future2 = pool.submit(new Callable<Boolean>() { public Boolean call() throws Exception { return 6 > 7; } }); System.out.println("线程的运行结果为:" + future2.get()); //取一个Runnable类型的任务 Future future3 = pool.submit(()->{ System.out.println(); }); } } 复制代码
其运行结果为
线程的运行结果为: 我爱java 线程的运行结果为:false 线程的运行结果为:null 复制代码
———— 线程池执行后先让其停止有什么方法呢?通常线程池的停止方法有两种:shutdown()和shutdownNow(),那么他们又有什么区别呢?
1.shutdown
/** * 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. * * <p>This method does not wait for previously submitted tasks to * complete execution. Use {@link #awaitTermination awaitTermination} * to do that. * * @throws SecurityException if a security manager exists and * shutting down this ExecutorService may manipulate * threads that the caller is not permitted to modify * because it does not hold {@link * java.lang.RuntimePermission}{@code ("modifyThread")}, * or the security manager's {@code checkAccess} method * denies access. */ void shutdown(); 复制代码
观看其源码的说明可以知道,shutdown()这种方法是有序的进行停止,在此之前提交的任务都可以继续执行,而执行此方法后如果继续往线程池丢任务,则不会再去执行任务。
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test01 { public static void main(String[] args) throws Exception { ExecutorService pool = Executors.newFixedThreadPool(1); for (int i = 0; i < 6; i++) { System.err.println(i); pool.execute(() -> { try { Thread.sleep(1000); System.out.println("我爱java,我爱学习"); } catch (Exception e) { e.printStackTrace(); } }); } Thread.sleep(2000); //停止线程池 pool.shutdown(); pool.execute(()->{ System.out.println("我不想上班"); }); } } 复制代码
运行结果
0 1 2 3 4 5 我爱java,我爱学习 我爱java,我爱学习 Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.test.Test01$$Lambda$2/2129789493@27d6c5e0 rejected from java.util.concurrent.ThreadPoolExecutor@4f3f5b24[Shutting down, pool size = 1, active threads = 1, queued tasks = 3, completed tasks = 2] at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047) at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369) at com.test.Test01.main(Test01.java:22) 我爱java,我爱学习 我爱java,我爱学习 我爱java,我爱学习 我爱java,我爱学习 复制代码
通过测试我们先创建一个大小为1的线程池,往里面丢6个任务,然后调用shutdown()方法去停止线程池,最后我们再去执行一个任务 可以发现我们刚开始放进去的任务都有序的执行了,当我们执行为shutdown()方法后,再去调用线程池,此时线程池已经不工作了。
2.shutdownNow()
/** * Attempts to stop all actively executing tasks, halts the * processing of waiting tasks, and returns a list of the tasks * that were awaiting execution. * * <p>This method does not wait for actively executing tasks to * terminate. Use {@link #awaitTermination awaitTermination} to * do that. * * <p>There are no guarantees beyond best-effort attempts to stop * processing actively executing tasks. For example, typical * implementations will cancel via {@link Thread#interrupt}, so any * task that fails to respond to interrupts may never terminate. * * @return list of tasks that never commenced execution * @throws SecurityException if a security manager exists and * shutting down this ExecutorService may manipulate * threads that the caller is not permitted to modify * because it does not hold {@link * java.lang.RuntimePermission}{@code ("modifyThread")}, * or the security manager's {@code checkAccess} method * denies access. */ List<Runnable> shutdownNow(); 复制代码
观看其源码的说明可以知道,shutdownNow()这种方法是停止所有线程(正在执行的和等待的),并返回任务列表(等待执行的任务),已经执行的任务是不会返回的,我们可以通过代码去验证
import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test01 { public static void main(String[] args) throws Exception { ExecutorService pool = Executors.newFixedThreadPool(1); for (int i = 0; i < 6; i++) { System.err.println(i); pool.execute(() -> { try { //1秒执行一个 Thread.sleep(1000); System.out.println("我爱java,我爱学习"); } catch (Exception e) { e.printStackTrace(); } }); } //休眠两秒 Thread.sleep(2000); List<Runnable> runnables= pool.shutdownNow(); System.out.println("未执行的线程"+runnables); System.out.println("未执行的线程的数量"+runnables.size()); } } 复制代码
运行结果
0 1 2 3 4 5 我爱java,我爱学习 我爱java,我爱学习 未执行的线程[com.test.Test01$$Lambda$1/931919113@7ef20235, com.test.Test01$$Lambda$1/931919113@7ef20235, com.test.Test01$$Lambda$1/931919113@7ef20235, com.test.Test01$$Lambda$1/931919113@7ef20235] 未执行的线程的数量4 复制代码
通过上面代码演示,我们先放6个任务进如线程池,每秒执行一个,然后休眠2秒,通过运行结果我们可以知道在休眠的2秒钟执行了两个线程,所以还有四个线程未执行,输出结果为4;
当我们把休眠时间变为2500毫秒(2.5秒)其输出结果为:
0 1 2 3 4 5 我爱java,我爱学习 我爱java,我爱学习 未执行的线程[com.test.Test01$$Lambda$1/931919113@7ef20235, com.test.Test01$$Lambda$1/931919113@7ef20235, com.test.Test01$$Lambda$1/931919113@7ef20235] 未执行的线程的数量3 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.test.Test01.lambda$main$0(Test01.java:14) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) 复制代码
可以看到当我们让其休眠2.5秒后。在这段时间执行完成了2个线程,第三个线程正在执行,而shutdownNow()方法是停止所有线程,返回正在等待执行的线程。所以其返回正在执行的数量为3