创建线程的方式
通常情况下我们一般使用两种方式来创建线程,即继承Thread和实现runnable接口,这两种创建方式线程执行完是没有返回结果的。其实还有第三种方式,那就是实现callable接口,该中方式线程执行完具有返回结果,下面将会从代码角度来分别讲解三种实现方式。
继承Thread
public class Main {
public static void main(String []args){
MyThread thread = new MyThread();
thread.start();
System.out.println("main------"+Thread.currentThread().getName());
}
public static class MyThread extends Thread{
@Override
public void run() {
try {
System.out.println("before sleep..."+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("after sleep..."+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 输出
before sleep...Thread-0
main------main
after sleep...Thread-0
实现runnable接口
public class Main {
public static void main(String []args){
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
Thread thread1 = new Thread(myRunnable);
thread1.start();
System.out.println("main------"+Thread.currentThread().getName());
}
public static class MyRunnable implements Runnable{
@Override
public void run() {
try {
System.out.println("before sleep..." + Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("after sleep..." + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 输出
main------main
before sleep...Thread-0
before sleep...Thread-1
after sleep...Thread-0
after sleep...Thread-1
实现callable接口
Callable并不像Runnable那样通过Thread的start方法就能启动实现类的run方法,它通常利用ExecutorService的submit方法去启动call方法自执行任务,而ExecutorService的submit又返回一个Future类型的结果,因此Callable通常也与Future一起使用。
public class CallableAndFutureTest {
public static void main(String []args){
//创建线程池 创建一个单线程化的线程池
ExecutorService es = Executors.newSingleThreadExecutor();
//创建Callable对象任务
MyCallable calTask=new MyCallable();
//提交任务并获取执行结果
Future<Integer> future =es.submit(calTask);
//关闭线程池
es.shutdown();
try {
System.out.println("主线程在执行其他任务 ----"+Thread.currentThread().getName());
// 获取异步执行的结果,如果没有结果可用,此方法会阻塞直到异步计算完成。
if(future.get()!=null){
//输出获取到的结果
System.out.println("future.get()-->"+future.get());
}else{
//输出获取到的结果
System.out.println("future.get()未获取到结果");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("主线程在执行完成----"+Thread.currentThread().getName());
}
public static class MyCallable implements Callable<Integer> {
private int sum;
@Override
public Integer call() throws Exception {
System.out.println("Callable子线程开始计算啦! ----"+Thread.currentThread().getName());
Thread.sleep(2000);
for(int i=0 ;i<5000;i++){
sum=sum+i;
}
System.out.println("Callable子线程计算结束!----"+Thread.currentThread().getName());
return sum;
}
}
}
// 输出
Callable子线程开始计算啦! ----pool-1-thread-1
主线程在执行其他任务 ----main
Callable子线程计算结束!----pool-1-thread-1
future.get()-->12497500
主线程在执行完成----main
当然callable还能和FutureTask结合使用,具体如何使用如下:
public class CallableAndFutureTest {
public static void main(String []args){
testCallableAndFutureTask();
}
public static void testCallableAndFutureTask(){
//创建线程池 创建一个单线程化的线程池
ExecutorService es = Executors.newSingleThreadExecutor();
//创建Callable对象任务
MyCallable calTask=new MyCallable();
//提交任务并获取执行结果
FutureTask<Integer> futureTask = new FutureTask<Integer>(calTask);
es.submit(futureTask);
//关闭线程池
es.shutdown();
try {
System.out.println("主线程在执行其他任务 ----"+Thread.currentThread().getName());
// 获取异步执行的结果,如果没有结果可用,此方法会阻塞直到异步计算完成。
if(futureTask.get()!=null){
//输出获取到的结果
System.out.println("future.get()-->"+futureTask.get());
}else{
//输出获取到的结果
System.out.println("future.get()未获取到结果");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("主线程在执行完成----"+Thread.currentThread().getName());
}
public static class MyCallable implements Callable<Integer> {
private int sum;
@Override
public Integer call() throws Exception {
System.out.println("Callable子线程开始计算啦! ----"+Thread.currentThread().getName());
Thread.sleep(2000);
for(int i=0 ;i<5000;i++){
sum=sum+i;
}
System.out.println("Callable子线程计算结束!----"+Thread.currentThread().getName());
return sum;
}
}
}