java 创建线程的方式
1.继承 Thread 类实现多线程
- start方法
start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。
- run方法
run()方法是不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。
class MyThread extends Thread{
@Override
public void run() {
synchronized (object) {
i++;
System.out.println("i:"+i);
try {
System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");
i++;
System.out.println("i:"+i);
}
}
}
2.实现 Runnable 接口
只是一个接口,它里面只有一个run()方法,没有start()方法。
3.实现 Callable 接口
- Executor 框架中还有一种方法可以实现异步,那就是实现 Callable 接口并重写call方法。
- 虽然是实现 Callable ,但是在 Executor 实际运行时,会将 Runnable 的实例或 Callable 的实例转化为 RunnableFuture 的实例。
- RunnableFuture 继承了 Runnable 和 Future 接口,这点将在下文详细解释。了解到这些 ,那么它和 Runnable 有什么不同呢?
- Callable 与 Runnable 相比不同点:
Callable 可以在任务结束的时候提供一个返回值,Runnable 无法提供这个功能。
Callable 的 call 方法分可以抛出异常,而 Runnable 的 run 方法不能抛出异常。
4.线程池
线程池就是有N个子线程共同在运行的线程组合。
线程池原理
线程池可以减少创建和销毁线程的次数,从而减少系统资源 的消耗,当一个任务提交到线程池时
- 首先判断核心线程池中的线程是否已经满了,如果没满,则创建一个核心线 程执行任务,否则进入下一步
- 判断工作队列是否已满,没有满则加入工作队列,否则执行下一步
- 判断线程数是否达到了最大值,如果不是,则创建非核心线程执行任务,否 则执行饱和策略,默认抛出异常
ThreadPoolExecutor
java.uitl.concurrent.ThreadPoolExecutor类是线程池中最核心的一个类,因此如果要透彻地了解Java中的线程池,必须先了解这个类。
- Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的;
- ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;
- 抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法。
閱讀更多 天天面試題 的文章