Java线程
在Java中,开启一个线程的唯一方式是,是通过Thread的start方法,并且在线程中执行的Runnable的run方法。无论是线程池还是Callable,Future,最核心最根本的还是调用到Thread.start()–>Runnable.run()
,其他的类的出现可以认为是更方便的使用Thread和Runnable,以此为核心会更容易理解Java的并发框架。
虽然Thread和Runnable类使得多线程编程简单直接,但有一个缺陷就是:在执行完任务之后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。
线程接口Runnable和Callable
Callable接口和Runnable接口相似,区别就是Callable需要实现call方法,而Runnable需要实现run方法;并且,call方法还可以返回任何对象,无论是什么对象,JVM都会当作Object来处理。但是如果使用了泛型,我们就不用每次都对Object进行转换了,Callable能够抛出exception,而Runnable不可以。
Runnable
public interface Runnable {
public abstract void run();
}
Callable
public interface Callable<V> {
V call() throws Exception;
}
Runnable和Thread
Thread实现了Runnable接口(可以认为Thread是Runnable的子类)
public class Thread implements Runnable
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("--------");
}
});
t.start();
}
Callable和Future
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
Future<Integer> result = executor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("--------");
Thread.sleep(3000);
int sum = 0;
for (int i = 0; i < 100; i++)
sum += i;
return sum;
}
});
executor.shutdown();
try {
System.out.println("task运行结果" + result.get());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("所有任务执行完毕");
}
//执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法
public interface Executor {
//在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。
void execute(Runnable command);
}