线程调度
- 线程状态:
- 状态切换
- 阻塞与唤醒
- 阻塞
- 唤醒
- wait 与 sleep
- 创建线程方式
线程是cpu任务调度的最小执行单位,每个线程拥有自己独立的程序计数器、虚拟机栈、本地方法栈。
线程状态:
线程状态包括:创建、就绪、运行、阻塞、死亡。
状态切换
方法 | 作用 | 区别 |
---|---|---|
start | 启动线程,由虚拟机自动调度执行run()方法 | 线程处于就绪状态 |
run | 线程逻辑代码块处理,JVM调度执行 | 线程处于运行状态 |
sleep | 让当前正在执行的线程休眠(暂停执行) | 不释放锁 |
wait | 使得当前线程等待 | 释放同步锁 |
notify | 唤醒在此对象监视器上等待的单个线程 | 唤醒单个线程 |
notifyAll | 唤醒在此对象监视器上等待的所有线程 | 唤醒多个线程 |
yield | 停止当前线程,让同等优先权的线程运行 | 用Thread类调用 |
join | 使当前线程停下来等待,直至另一个调用join方法的线程终止 | 用线程对象调用 |
线程状态切换:
阻塞与唤醒
阻塞
这三个方法的调用都会使当前线程阻塞。该线程将会被放置到对该Object的请求等待队列中,然后让出当前对Object所拥有的所有的同步请求。线程会一直暂停所有线程调度,直到下面其中一种情况发生:
其他线程调用了该 Object 的 notify 方法,而该线程刚好是那个被唤醒的线程;
其他线程调用了该 Object 的 notifyAll 方法。
唤醒
线程将会从等待队列中移除,重新成为可调度线程。
它会与其他线程以常规的方式竞争对象同步请求。
一旦它重新获得对象的同步请求,所有之前的请求状态都会恢复,也就是线程调用 wait 的地方的状态。
线程将会在之前调用 wait 的地方*继续运行下去。
由于 wait() 属于 Object 方法,调用之后会强制释放当前对象锁,所以在 wait() 调用时必须拿到当前对象的监视器 monitor 对象。因此,wait() 方法在同步方法/代码块中调用。
wait 与 sleep
- wait 方法必须在 synchronized 保护的代码中使用,而 sleep 方法并没有这个要求。
- wait 方法会主动释放 monitor 锁,在同步代码中执行 sleep 方法时,并不会释放 monitor 锁。
- wait 方法意味着永久等待,直到被中断或被唤醒才能恢复,不会主动恢复,sleep 方法中会定义一个时间,时间到期后会主动恢复。
- wait/notify 是 Object 类的方法,而 sleep 是 Thread 类的方法。
创建线程方式
1.实现 Runnable 接口(优先使用)
public class RunnableThread implements Runnable {
@Override
public void run() {
System.out.println("实现Runnable接口,实现线程");
}
}
2.实现Callable接口(有返回值可抛出异常)
class CallableTask implements Callable<Integer> {
@Override
public Integer call() throws Exception {
return new Random().nextInt();
}
}
3.继承Thread类(java不支持多继承)
public class ExtendsThread extends Thread {
@Override
public void run() {
System.out.println("用Thread类实现线程");
}
}
4.使用线程池(底层都是实现run方法)
static class DefaultThreadFactory implements ThreadFactory {
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "pool-" + poolNumber.getAndIncrement() +"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);
if (t.isDaemon())
t.setDaemon(false); //是否守护线程
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY); //线程优先级
return t;
}
}
原文:https://mp.weixin.qq.com/s/IVgGXQKU1QiT1ToN2wXHJg