多线程基础 - 状态、创建、常用方法
线程状态
java.lang.Thread.State
里明确了线程的各个状态以及怎么进入和退出各个状态
public enum State {
// 初始化状态,线程创建之后的状态,new Thread() 之后进入
NEW,
// 就绪状态,线程正在运行或等待 CPU 时间片,调用了 线程的 start() 方法进入
RUNNABLE,
// 阻塞状态,synchronized 代码块或方法
BLOCKED,
/**
* 无限期等待状态,如果不手动唤醒就一直持续该状态
* 当调用了不带时间的 Object.wait() 进入该状态(退出状态:Object.notify() / Object.notifyAll())
* 当调用了不带时间的 Thread.join() 进入该状态(退出状态:加入的线程执行完毕)
* 当调用了 LockSupport.park() 进入该状态(退出状态:给线程颁发令牌,LockSupport.unpark(thread))
*/
WAITING,
/**
* 期限等待,达到条件后会自动唤醒,无需手动唤醒
* 当调用了 Thread.sleep() 进入该状态(不管带不带时间都是期限等待,虽然不带时间会一直等,这样有点像无限期等待,但是确实进入了期限等待)
* 当调用了带时间的 Object.wait() 进入该状态(退出状态:时间结束 / Object.notify() / Object.notifyAll())
* 当调用了带时间的 Thread.join() 进入该状态(退出状态:时间结束 / 加入的线程执行完毕)
* 当调用了 LockSupport.parkNanos() 进入该状态(退出状态:时间结束)
* 当调用了 LockSupport.parkUntil() 进入该状态(退出状态:到指定时刻)
*/
TIMED_WAITING,
// 运行结束
TERMINATED;
}
创建线程
继承 Thread
class MyThread1 extends Thread{
@Override
public void run(){
System.out.println("继承 Thread ...");
}
}
public class Test1 {
public static void main(String[] args) {
new MyThread1().start();
}
}
实现 Runnable
class MyThread implements Runnable{
@Override
public void run() {
System.out.println("继承 Runnable ......");
}
}
public class Test1 {
public static void main(String[] args) {
// 创建真实对象
MyThread myThread = new MyThread();
// 创建代理对象
Thread t = new Thread(myThread);
t.start();
}
}
// 匿名内部类
new Thread(() -> {
System.out.println("匿名内部类方式 ......");
}).start();
实现 Callble
// 借助线程池
class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
return "hello world!";
}
}
public class Test1 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建对象
MyThread myThread = new MyThread();
// 创建线程, 使用线程调度服务来创建, 参数表示创建线程的数量
ExecutorService t = Executors.newFixedThreadPool(1);
// 执行线程
Future<String> result = t.submit(myThread);
// 获取线程执行结果的返回值, 将会等待线程执行结束
String s = result.get();
System.out.println(s);
// 停止线程池
t.shutdownNow();
}
}
// 使用 FutureTask 封装
FutureTask<Integer> ft = new FutureTask<>(() -> {
return 123 + 123;
});
new Thread(ft).start();
Integer integer = ft.get();
常用方法
方法名 | 作用 | 特点 |
---|---|---|
start() | 启动线程,线程进入可运行状态 | 不是立马执行,还需要等一个时机,等抢到 CPU 调度权就执行 |
join() | 加入线程,等加入的线程执行结束再执行当前线程 | |
sleep() | 线程休眠,让出 CPU 执行权,等到休眠时间到了才会再次争夺 CPU 执行权,休眠期间不会再次争夺 CPU 执行权 | 不会释放锁 |
yield() | 线程让步,让出 CPU 执行权,强制进入就绪状态,可能刚让出 CPU 执行权立马又获取到了 | 不会释放锁 |
wait() | 线程等待,让出 CPU 执行权,notify/notifyAll 之后才会再次争夺 CPU 执行权 必须同时获取到锁和得到 CPU 执行权才会执行 |
会释放锁 |
notify()/notifyAll() | 唤醒等待当前锁的线程(唤醒的线程必须拿到释放的锁才可能执行,和 wait 必须持有同一把锁) | 会释放锁 |
setPriority(int newPriority) | 设置线程优先级 | 范围 1-10 |
getPriority() | 获取线程优先级 | |
setName(String name) | 设置线程名称 | 如果不指定, 默认 Thread-index |
getName() | 获取线程名称 | |
currentThread() | 静态方法, 返回当前线程 |