多线程
一、 实现线程的方式
在JAVA中,创建线程就是创建Thread类(子类)的对象(实例)
java.lang.Thread
1. 继承Thread类
例如:
class ThreadTest extends Thread{ public void run(){ System.out.println("这个线程开始运行"); } } public class Test { public static void main(String[] args) { ThreadTest tt = new ThreadTest (); tt.start(); //启动一个线程 } }
2. 实现Runnable接口(优先使用)
class ThreadTest implements Runnable{ public void run(){ System.out.println("这个线程开始运行"); } } public class Test { public static void main(String[] args) { ThreadTest tt = new ThreadTest (); Thread t = new Thread(tt); t.start(); //通过一个线程对象启动它 } }
这两种方式的区别:
1、继承Thread类:编写简单,可直接操作线程。适用于单继承
2、实现Runnable接口:避免单继承局限性,便于共享资源。
推荐使用实现Runnable接口方式创建线程
3. 实现Callable接口(了解)
import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; //创建Callable接口实现类,并实现call()方法,此方法为线程执行体,且有返回值 class CallableThreadTest implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("执行线程"); return 1; } } public class Test { public static void main(String[] args) { //使用FutureTask类(实现了Future和Runnable接口)来包装Callable对象 FutureTask<Integer> ft = new FutureTask<>(new CallableThreadTest()); //使用FutureTask对象作为Thread对象的target创建并启动新线程 new Thread(ft).start(); //调用FutureTask对象的get()方法来获得子线程执行结束后的返回值 try { System.out.println("子线程的返回值:" + ft.get()); } catch (Exception e) { e.printStackTrace(); } } }
Runnable和Callable的区别:
- Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。
- Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
- call方法可以抛出异常,run方法不可以。
- 运行Callable任务可以拿到一个Future对象。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
二、 线程的生命周期
- [NEW]新建状态
尚未启动的线程处于此状态。新创建了一个线程对象,但未调用start方法 - [RUNNABLE]就绪状态,即可运行状态,复合状态
包含ready和running两个状态
ready:表示该线程处于可被调度调度的状态
运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
Thread.yield()方法可以将线程由Running状态变为ready 状态 - [BLOCKED]阻塞状态
被阻塞等待监视器锁定的线程处于此状态。
线程发起I/O操作或者申请由其他线程独占的资源,不占用CPU
当阻塞I/O执行完毕可或者获得了申请的资源,状态就变为RUNNABLE
阻塞I/O是指,进程会一直阻塞,直到数据拷贝完成;阻塞I/O模式时最普遍使用的I/O模式,如输入、输出、接受连接等
- [WAITING]
正在等待另一个线程执行特定动作的线程处于此状态。
线程执行了object.wait() 或thread.join()方法就会把线程转换为等待状态,执行object.notify()方法或者加入的线程执行完毕,线程将重回RUNNABLE状态
(傻傻的等)
- [TIMED_WAITING]
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
与WAITING的区别是不会无限期的等待,而是等待指定时间后不管期望的操作是否执行完毕,线程都将重回RUNNABLE状态
(只等等指定长度的时间)
- [TERMINATED]终止状态
已退出的线程处于此状态。
三、 线程调度的常用方法
方法 |
功能 |
getName() setName() |
设置或获取当前线程名称 |
isAlive() |
判断线程是否存活(就绪、运行、阻塞是存活状态) |
getPriority() |
获取线程优先级 |
setPriority() |
设置线程优先级 |
Thread.sleep() |
强迫线程睡眠(单位:毫秒)(不释放同步锁) |
join() |
等待某线程结束,再恢复当前线程的运行 |
yield() |
让出CPU资源,当前线程进入就绪状态 |
wait() |
当前线程进入等待状态,即进入等待池。(释放同步锁,由notify()唤醒) |
notify() notifyAll() |
唤醒等待池中的某个或全部等待线程 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)