Java多线程基础梳理
Java多线程基础梳理
Java给多线程编程提供了内置的支持。一条线程指的是进程中(正在运行的一个应用,包括操作系统分配的内存空间,一个或者多个线程)的一个单一顺序的控制流,一个进程中可以并发执行多个线程,没个线程并发的执行不同的任务。
多线程是多任务的一种特别的形式,但是多线程使用了更小的资源开销。
一个线程的生命周期
-
新建状态
-
使用new关键字和Thread类或其子类建立一个线程对象后,该线程就处于新建状态。它保持这个状态直到程序start()这个线程。
-
-
就绪状态
-
当线程对象调用start()方法之后,该线程就处于就绪状态。就绪状态的线程处于就绪队列中,要等待JVM中线程调度器的调度。
-
-
运行状态
-
如果就绪状态的线程获取CPU资源,就可以执行run()方法,此时线程处于运行状态。
-
-
阻塞状态
-
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
-
等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
-
同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
-
其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
-
-
-
死亡状态
-
一个运行状态的线程完成任务或者其他终止条件触发时,该线程就切换为死亡状态。
-
如何创建一个线程
继承Thread类
创建线程的第一个方法就是继承Thread类,该类必须重写Thread中的run()方法,run()方法是新线程的入口点,调用的时候必须使用start方法才能够执行。
//创建TestThread01继承Thread类
//注意:线程开启之后不一定立即执行,线程执行由CPU统一调度
public class TestThread01 extends Thread{
//重写run()方法
小结
-
子类继承Thread类具备多线程能力
-
启动线程:子类对象.start()
-
testThread01.start();
-
-
不建议使用,避免OOP单继承局限性
实现Runnable接口
创建线程的第二个方法就是实现Runnable接口,该类也需要重写run()方法,将需要执行的线程放置到Runnable接口的实现类中,调用start()方法执行
//创建线程方式2.实现Runnable接口,重写run方法,执行线程需要丢入Runnable接口的实现类,调用start方法
public class TestThread02 implements Runnable{
//重写run()方法
小结
-
实现接口Runnable具有多线程能力
-
启动线程:传入目标对象.Thread对象.start()
-
new Thread(目标对象).start();
-
-
推荐使用,避免单继承局限性,灵活方便,方便同一个对象呗多个线程调用
通过Callable创建线程
1.实现Callable接口,需要返回值类型
2.重写call方法,需要抛出异常
3.创建目标对象
4.创建执行任务:ExecutorService ser = Executors.newFixedThreadPool(1);
5.提交执行:Future<Boolean> result = ser.submit(t1);
6.获取结果:boolean r1 = result.get()
7.关闭服务:ser.shutdown();
import java.util.concurrent.*;
//实现Callable方式创建线程
public class TestThread05 implements Callable<Boolean> {
//重写call()方法