Java多线程—创建多线程的两种方式
JDK新增的创建多线程的两种方式——Callable和线程池
Callable实现多线程
重写call方法
可以向线程传递数据,可以向上报一个异常
需要借助Future接口(FutureTask类)
1、创建并实现一个Callable的实现类MyCallable
2、实现call方法,将此线程需要执行的操作声明在call()中,可带有返回值
3、创建Callable接口实现类的对象myCallable
4、将Callable接口实现类的对象传递到FutureTask构造器中,创建FutureTask的对象
5、将FutureTask的对象作为参数传递到Thread类的构造器中,创建线程对象并调用start()
6、可以去获取Callable中call()的返回值——futureTask.get()
public class CallableTest {
public static void main(String[] args) {
MyCallable myCallable=new MyCallable();
FutureTask futureTask=new FutureTask(myCallable);
new Thread(futureTask).start();
try {
int result=(Integer) futureTask.get();
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable {
@Override
public Object call() throws Exception{
int sum=0;
for(int i=0;i<=100;i++){
System.out.println(i);
sum+=i;
}
return sum;
}
}
> 理解:Callable接口比Runnable更强大 1、call()可以有返回值 2、call()可以抛出异常,被外面的操作捕获,获取异常的信息 3、Callable支持泛型
线程池实现多线程
public class ThreadPoolTest {
public static void main(String[] args) {
ExecutorService service= Executors.newFixedThreadPool(10);
//设置线程池属性,特殊点
ThreadPoolExecutor serviceExecutor = (ThreadPoolExecutor) service; //因为前面service是接口多态的引用,
// 不能调用实现类的属性变量和getset方法
// ThreadPoolExecutor serviceExecutor2= (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
// serviceExecutor2.execute(new MyRun1()); //ps:这也意味着上述接口的实现类也可以直接使用execute()
//serviceExecutor.setMaximumPoolSize(15); //设置池中最大线程数
//serviceExecutor.setKeepAliveTime(10000); //设置线程没任务时最多保持多久之后终止
service.execute(new MyRun1()); //从线程池中拿到一个线程并执行,使用Runnable接口
service.execute(new MyRun2());
// service.submit(Callable callable); //使用Callable接口
service.shutdown(); //关闭线程池
}
}
使用线程池的好处:
-提高相应速度(减少创建新线程的时间)
-降低资源消耗(重复利用线程池中的线程,不需要每次都创建)
-便于线程管理
.corePoolSize:核心池的大小
.maximumPoolSize:最大线程数
.keepAliveTime:线程没有任务是最多保持多长时间后会终止