线程在java面试时,一般是常问的一个点了,今天咱们来聊聊线程
- 概念
线程是指进程中的一个执行流程,一个进程可以运行多个线程,线程总是属于某个进程,进程中的多个线程共享进程的内存
进程是指一个内存中运行的应用程序
- 生命周期
新建状态:创建线程
就绪状态:此线程具备除了时间片以外的所有资源,等待运行
运行状态:抢占到时间片进入到运行期
阻塞状态:由运行状态被阻塞,如调用sleep方法
死亡状态:线程结束
- 线程实现的方式
方法一:继承Thread类,再累中将任务写出(重写run方法),线程和任务是绑定的,耦合度高,通过Thread.currentThread()方法或者this获取当前线程
public class TestThread extends Thread{ @Override public void run() { System.out.println("重写run()方法"); } public static void main(String[] args) { TestThread thread = new TestThread(); thread.start();//启动线程 } }
方法二:实现Runnable接口(重写run()方法),实现类中将任务写出,此时线程和任务是分离的,使用更灵活, 通过Thread.currentThread()方法获取当前线程
public class TestRunnable implements Runnable { @Override public void run() { System.out.println("实现Runnable 重写run方法"); } public static void main(String[] args) { TestRunnable target = new TestRunnable(); Thread thread = new Thread(target); thread.start();//启动线程 } }
方法三:实现callable接口(重写call()方法), 通过Thread.currentThread()方法获取当前线程
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class TestCallable implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("继承Callable接口 实现call方法作为线程执行体 有返回值"); return 100; } public static void main(String[] args) throws ExecutionException, InterruptedException { Callable<Integer> testCallable = new TestCallable(); FutureTask<Integer> futureTask = new FutureTask<Integer>(testCallable); Thread thread = new Thread(futureTask);//FutureTask实现了Runnable 可以作为Thread对象的target来创建线程。 thread.start();//启动线程 Integer result = futureTask.get();//调用FutureTask对象的get()方法来获得子线程执行结束后的返回值 } }
- 守护线程
守护线程和普通线程本质上没有区别,只需要通过Thread提供的void setDaemon(boolean) ,参数为true时,该线程为守护线程。
守护线程又称为后台线程,创建出来的线程默认为前台线程,守护线程和普通线程的区别在于结束,当所有前台线程都结束时,进程结束,无论改进程中的守护线程是否还在运行,都要强制结束
GC就是守护线程