1、线程相关概念
1)、线程与进程的区别
线程是操作系统调度的最小单元,也叫轻量级进程,而进程是操作系统中的应用程序,在进程中可以创建多个线程。
2)、上下文切换
我们知道现代处理器都是多核的,几核处理器只能同时处理几个线程,多线程执行程序看起来是同时进行,实际上是CPU在多个线程之间快速切换执行,这中间就涉及到上下问切换,所谓的上下文切换就是指一个线程T被分配的时间片用完了之后,线程的信息被保存起来,CPU执行另外的线程,再到CPU读取线程T的信息并继续执行T的过程。
2、线程实现方式
1)、继承Thread类
由于类的单继承性,使用这种方式实现就无法再去继承其他的线程,有局限,耦合度高。
public class MyThread extends Thread{ @Override public void run() { super.run(); System.out.println("我继承了Thread类..."); } }
2)、实现Runnable接口
大多数都用这种方式实现,很灵活,重写run()方法即可,run() 方法没有返回值。
3)、实现Callable接口
若是想获取到线程的执行结果,那就用这种方式,它和实现Runnable接口的区别是要重写call()方法,call()方式是有返回值的,返回的Object是任务的执行结果,可以用Future接口的实现类FutureTask来接收,并调用get()方法获取到执行结果。另外call()方法可抛出异常,而run()方法是不能抛出异常的
public class Test { public static void main(String[] args) throws Exception { Thread thread1 = new MyThread(); thread1.start(); Thread thread2 = new Thread(new MyRunnable()); thread2.start(); Callable callable = new MyCallable(); FutureTask<String> future = new FutureTask<>(callable); ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.submit(future); System.out.println(future.get()); executorService.shutdown(); } static class MyRunnable implements Runnable{ @Override public void run() { System.out.println("我实现了Runnable接口..."); } } static class MyCallable implements Callable{ @Override public String call() throws Exception { return "我实现了Callable接口..."; } } }
执行结果:
我继承了Thread类...
我实现了Runnable接口...
我实现了Callable接口...
3、线程状态
根据jdk中Thread类的State内部类,线程有6种状态,下次面试官问你线程有几种状态,你可以很有底气的回答:6种,如下左图,右图是线程状态之间的转换。

这里注意:线程在等待进入synchronzed方法或者synchronized块时的线程状态时BLOCKED,而在等待进入lock锁时的状态是WAITING或者TIME_WAITING,因为lock是用LockSupport实现的(源码还没研究)。
测试如下:
public class MyService { public static synchronized void serviceMethod1(){
try{
System.out.println(Thread.currentThread().getName+"进入了业务方法");
Thread.sleep(millis: 1000);
} catch (Execption e){
e.printStackTrace();
}
}

