01 通常线程池的执行方法有两种execute和submit,那么他们有什么区别呢?
1.接受任务的类型
execute 只能接受Runnable类型的任务
void execute(Runnable command);
submit不管是Runnable还是Callable类型的任务都可以接受,但是Runnable返回值均为void,所以使用Future的get()获得的还是null
Future submit(Callable task);
Future 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 future = pool.submit(new Callable() {
public String call() throws Exception {
return "我爱java";
}
});
String result = future.get();
System.out.println("线程的运行结果为: " + result);
//我们取一个boolean类型的返回值
Future future2 = pool.submit(new Callable() {
public Boolean call() throws Exception {
return 6 > 7;
}
});
System.out.println("线程的运行结果为:" + future2.get());
//取一个Runnable类型的任务
Future future3 = pool.submit(()->{
System.out.println();
});
}
}
其运行结果为
线程的运行结果为: 我爱java
线程的运行结果为:false
线程的运行结果为:null
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.
*
*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();
image
观看其源码的说明可以知道,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.
*
*This method does not wait for actively executing tasks to
* terminate. Use {@link #awaitTermination awaitTermination} to
* do that.
*
*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 shutdownNow();
image
观看其源码的说明可以知道,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 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
网友评论