-
前言:
雖然java的API中說創建多線程的方式只有兩種(There are two ways to create a new thread of execution),分別是繼承
Thread
類創建和實現Runnable
接口創建,在上一篇博文中演示了這兩種,詳見,但是JDK5.0以后新增了兩種,分別是實現Callable
接口創建和使用線程池
創建,本次就演示后兩種創建方式並分析其特性。
-
實現
Runnable
接口創建多線程創建步驟:
1.創建一個實現
Callable
接口的類。2.重寫call()方法,線程需要執行的代碼都放到call方法中。
3.創建實現
Callable
接口類的實例對象。4.將步驟 3 的對象作為參數傳給
FutureTask
構造器中,創建FutureTask
對象。5.將
FutureTask
的對象作為參數傳給Thread
類,創建對象並調用start()方法。
package day02;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//創建一個多線程,輸出20以內的偶數,並返回所有偶數的和
//1.創建一個實現`Callable`接口的類。
class TestSum implements Callable{
//2.重寫call()方法,線程需要執行的代碼都放到call方法中。
@Override
public Object call() throws Exception{
int sum = 0;
for(int i = 1;i <= 20 ;i++ ){
if(i % 2 == 0){
System.out.println(i);
sum = sum + i;
}
}
return sum;
}
}
public class ThreadCall {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//3.創建實現`Callable`接口類的實例對象。
TestSum test = new TestSum();
//4.將步驟 3 的對象作為參數傳給`FutureTask`構造器中,創建`FutureTask`對象。
FutureTask futuretask = new FutureTask(test);
//5.將`FutureTask`的對象作為參數傳給`Thread`類,創建對象並調用start()方法。
Thread thread = new Thread(futuretask);
thread.start();
//get方法可以獲取返回值
System.out.println("偶數總合是:"+futuretask.get());
}
}
//輸出結果:
2
4
6
8
10
12
14
16
18
20
偶數總合是:110
實現Callable接口創建多線程的特點:
1.call()方法可以有返回值,可以使用get()方法獲取返回值。
2.call()方法可以拋出異常, 而且能被外面捕獲到。
3.Callable支持泛型。
-
使用線程池創建多線程
一.實現Runnable接口的方式創建:
package day02;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Number implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if (i % 2 == 0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
public class ThreadPool {
public static void main(String[] args){
ExecutorService service = Executors.newFixedThreadPool(10);
Number num = new Number();
service.execute(num);
service.shutdown();
二.實現Callable接口的方式創建:
package day02;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Number implements Callable {
@Override
public Object call() {
for (int i = 0; i < 20; i++) {
if (i % 2 == 0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
return null;
}
}
public class ThreadPool {
public static void main(String[] args){
ExecutorService service = Executors.newFixedThreadPool(10);
Number num = new Number();
service.submit(num);//區別在這里
service.shutdown();
}
}
-
線程池好處:
1.頻繁創建線程和銷毀使用量較大的資源,比如並發的線程,對性能影響較大,所以需要創建線 程池存放線程,使用的時候直接獲取,實現重復利用,提高效率。
2.降低創建線程時間,提高響應速度。
3.降低資源的消耗。
4.便於線程管理。