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】免費獲取資料和面試心得以及自己學習和經驗分享給大家,希望對大家可以有幫助。覺得有所收穫的話可以關注我和轉發分享給更多的程序猿們。


推薦閱讀:
相关文章