-
前言:
虽然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.便于线程管理。