1.实现Callable接口方式
和实现Runnable接口相比
- call()可以有返回值。
- call()可以抛出异常,被外面的操作捕获,获取异常信息。
- Callable是支持泛型的。
实现Callable接口的方式,线程计算0~100内的偶数
实现类,重写call()方法,可以返回值和抛出异常
public class NumThread implements Callable {
@Override
public Object call() throws Exception {
int sum = 0;
for (int i = 0; i < 100; i++) {
if (i%2==0){
System.out.println(i);
sum+=i;
}
}
return sum;
}
}
测试
public class Test {
public static void main(String[] args) {
NumThread numThread = new NumThread(); //实现类对象
FutureTask futureTask = new FutureTask(numThread); //numThread作为参数传递到构造器中,创建FutureTask对象
new Thread(futureTask).start(); //futuretask对象作为参数传递到thread类构造器中,创建thread对象,调用start启动线程
try {
Object sum = futureTask.get(); //获取call方法的返回值
System.out.println("总和为:"+sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
2.使用线程池方式
使用线程池的好处
- 提高响应速度(减少了创建新线程的时间)
- 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
- 便于线程管理
- corePoolSize:核心池的大小(最小线程数量,不会被销毁)
- maximumPoolSize:最大线程数
- keepAliveTime:线程没有任务时最多保持多长时间后会终止
线程1,打印100以内偶数
public class NumberThread1 implements Runnable{
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
if (i%2==0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
线程2,打印100以内奇数
public class NumberThread2 implements Runnable{
@Override
public void run() {
for (int i = 0; i <=100; i++) {
if (i%2!=0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
创建线程池执行线程,executors方式创建线程池。
public class ThreadPool {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(10); //创建固定大小的线程池
//执行指定线程,execute或submit方式
pool.execute(new NumberThread1());
pool.execute(new NumberThread2());
// pool.submit(Callable callable);
pool.shutdown(); //关闭线程池
}
}
ThreadPoolExecutor方式创建线程池可以设置其7个参数。
参考链接:
1.浅谈Java多线程之FutureTask
2.线程池的参数
3.java线程池ThreadPoolExecutor类使用详解
4.线程池的7种创建方式,强烈推荐你用它