6 线程
约 1372 字大约 5 分钟
2025-04-05
在java中线程只有六种状态,没有运行状态,因为当线程进入运行状态时jvm虚拟机就将该线程交给cpu运行了,所以对于jvm虚拟机来说不需要有运行状态
继承Thread类的方法
要自定义一个类继承Thread类并重写run方法,当开启线程时自动执行run方法 使用start方法开启线程
可以调用Thread中的成员方法
成员方法
方法名称 | 说明 |
---|---|
String getName() | 返回此线程的名称 |
void setName(String name) | 设置线程的名字 (构造方法也可以设置名字) |
staticc Thread currentThread() | 获取当前线程的对象 |
staticc void sleep(long time) | 让线程休眠指定的时间,单位为毫秒 |
setPriority(int newPriority) | 设置线程的优先级 |
final int getPriority() | 获取线程的优先级 |
final void setDaemon(boolean on) | 设置为守护线程 |
public static void yield() | 出让线程/礼让线程,当一个线程执行到该函数时就出让自己的执行权 |
public static void join() | 插入线程/插队线程,先执行这个线程 |
如果没有给线程设置名字它也是有默认名字的:Thread-编号 优先级越大抢到时间片的概率也越大,但并不意味着一定比它优先级低的线程先抢到 优先级从1到10,数字越大优先级越高 当非守护线程都执行完毕后会给守护线程发送一个信号,守护线程接收到信号后会陆续结束(并不是非守护线程结束瞬间结束)
线程同步
在多线程的场景下推荐使用StringBuffer,它和StringBuilder一样,但是线程安全的(所有的方法前都加了 synchronized 关键字修饰)
对于锁,因为java是面向对象的语言,很多时候一个对象都是写在一个类内部的,如果是锁对象写在类内部那么在多线程的场景下多个对象可能会有不同的锁,因此锁大多是使用static修饰的
synchronized
同步代码块
synchronized(锁){
操作共享数据的代码;
}
锁默认打开,有一个线程进去了,锁自动关闭 里面的代码全部执行完毕,线程出来,锁自动打开 锁可以使用Object对象来指代 示例
Object obj = new Object();
public void run(){
while(true){
//同步代码块
synchronized(obj){}
}
}
同步函数 将synchronized关键字用于修饰函数使这个函数能够上锁 锁住方法里面所有的代码
修饰符 synchronized 返回值类型方法名(方法参数){}
锁对象不能自己指定 如果是非静态方法锁对象就是this 如果是静态方法锁对象就是当前类的字节码文件对象
实现Runnable接口的方法
自定义一个类实现Runnable接口并重写run方法 使用start方法开启线程
利用Callable和Future实现
前两种方法都没有返回值,使用该方法可以获取多线程运行的结果 创建MyCallable类实现callable接口重写call方法(表示多线程要执行的任务) Future是一个抽象类所以不能创建对象可以创建它的实现对象FutureTask 创建FutureTask的对象(作用管理多线程运行的结果) 创建Thread类的对象,并启动(表示线程)
public class MyCallable implements Calllabel<Integer>{
@Override
public Integer call(){}
}
//创建MyCallable的对象(表示多线程要执行的任务)
MyCallable mc = new MyCallable();
//创建FutureTask的对象(作用管理多线程运行的结果)
FutureTask<Integer>ft = new FutureTask<>(mc);
//创建线程的对象
Thread t1 = new Thread(ft);
//启动线程
t1.start();
//获取多线程运行的结果
Integer result = ft.get();
System.out.println(result)
手动上锁/释放锁
获取lock对象再对其上锁
Lock lock=new ReentrantLock();
void lock(): 获得锁 void unlock():释放锁
唤醒
锁的成员函数
方法名称 | 说明 |
---|---|
void wait() | 当前线程等待,直到被其他线程唤醒 |
void notify() | 随机唤醒单个线程 |
void notifyAll() | 唤醒所有线程 |
阻塞队列
将任务放到一个队列中,当队列满时生产者被阻塞,队列空时消费者被阻塞
阻塞队列实现了4个接口 Iterable Collection Queue BlockingQueue 这些接口不可直接创建对象
两个实现类 ArrayBlockingQueue底层是数组,有界 LinkedBlockingQueue底层是链表,无界
线程池
通过工具类创建线程池
可以方便的创建线程池
Executors:线程池的工具类通过调用方法返回不同类型的线程池对象
方法名称 | 说明 |
---|---|
public static ExecutorService newCachedThreadPool() | 创建一个没有上限的线程池 |
public static ExecutorService newFixedThreadPool(int nThreads) | 创建有上限的线程池 |
void submit(task()) | 提交任务函数给线程池让它运行 |
void shutdown() | 销毁线程池 |
自定义线程池
- 参数一:核心线程数量不能小于0
- 参数二:最大线程数不能小于0,最大数量>=核心线程数量
- 参数三:空闲线程最大存活时间不能小于0
- 参数四:时间单位用TimeUnit指定
- 参数五:任务队列不能为null
- 参数六:创建线程工厂不能为null
- 参数七:任务的拒绝策略不能为null
ThreadPoolExecutor pool=new ThreadPoolExecutor(
3,
6,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
贡献者
版权所有
版权归属:PinkDopeyBug