01 通常线程池的执行方法有两种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

欢迎大家关注我,需要更多Java面试资料和学习干货可以关注我的专栏【Tom猫的Java屋】

Tom猫的java屋?

zhuanlan.zhihu.com图标

02 线程池执行后先让其停止有什么方法呢?通常线程池的停止方法有两种: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 managers {@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 managers {@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

03 读者福利

在这里小编整理了很多Java相关的学习资料给大家,还有面试资料和编程书籍。(适合所有Java工程师学)资料图和面试资料,架构资料!

资料获取方式后台私信【java】免费获取资料和面试心得以及自己学习和经验分享给大家,希望对大家可以有帮助。觉得有所收获的话可以关注我和转发分享给更多的程序猿们。


推荐阅读:
相关文章