本文要先理解上面以人为例的实例哦
多线程
label1:
多线程可以这么理解,以人为例,人的话只有一个大脑(CPU),可以存在多个进程,比如说,说话、行动、思考等等,此时,思考是一个进程对吧,比如你一边思考中午吃什么,一边思考这个Bug怎么解决,此时,这两个思考任务就是思考进程中的两个线程。
Runnable 接口
实现Runnable接口的类,比如说Thread,要想实现自己的多线程,必须Override这个接口的run方法,然后调用start方法来实现多线程,根据jdk的源码我们可以发现,Runnable的run方法是void类型的,也就是没有返回值的。
public abstract void run();
此时,如果以上面label1
中的例子来说,我们的思考只是一个简单的思考,即使想到答案,也不会放到问题所在的区域里,但是人不一样,可以理解为人有一个答案的寄存区域(类似于Redis),先把答案放到寄存区中,这如果在Java中,就需要写额外的代码了。
也就是说,Runnable接口的实现类都会存在一个问题,那就是不能接受返回值。
Callable
我写了一个Demo
package ZThread;
import java.util.concurrent.*;
public class MyCallable implements Callable {
public static void main(String[] args) throws Exception {
ThreadPoolExecutor tpe = new ThreadPoolExecutor(5, 10, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<>(16));
Future<String> future = tpe.submit(new MyCallable());
Future<String> future2 = tpe.submit(new MyCallable());
Future<String> future3 = tpe.submit(new MyCallable());
System.out.println("Start");
System.out.println(future.get());
System.out.println(future2.get());
System.out.println(future3.get());
//get 方法是阻塞的
System.out.println(tpe.submit(new MyCallable()).get());
System.out.println(tpe.submit(new MyCallable()).get());
System.out.println(tpe.submit(new MyCallable()).get());
System.out.println(tpe.submit(new MyCallable()).get());
System.out.println("End");
}
public Object call() throws Exception {
System.out.println("[S]= CURRENT THREAD NAME:" + Thread.currentThread().getName());// 调用时的输出
Thread.sleep(1000);
return String.valueOf("[O]= CURRENT THREAD NAME:" + Thread.currentThread().getName()); // 返回结果
}
}
输出结果
Start
[S]= CURRENT THREAD NAME:pool-1-thread-2
[S]= CURRENT THREAD NAME:pool-1-thread-1
[S]= CURRENT THREAD NAME:pool-1-thread-3
[O]= CURRENT THREAD NAME:pool-1-thread-1
[O]= CURRENT THREAD NAME:pool-1-thread-2
[O]= CURRENT THREAD NAME:pool-1-thread-3
[S]= CURRENT THREAD NAME:pool-1-thread-4
[O]= CURRENT THREAD NAME:pool-1-thread-4
[S]= CURRENT THREAD NAME:pool-1-thread-5
[O]= CURRENT THREAD NAME:pool-1-thread-5
[S]= CURRENT THREAD NAME:pool-1-thread-2
[O]= CURRENT THREAD NAME:pool-1-thread-2
[S]= CURRENT THREAD NAME:pool-1-thread-3
[O]= CURRENT THREAD NAME:pool-1-thread-3
End
有条件的读者可以试着运行一下,就会明白其中的逻辑了。
这里有个图解
其实也并不是说谁更优秀,他们的差异我感觉也就是有无返回值,如果不是,欢迎留言。