java中的多线程
java支持多线程,使得我们的程序在运行过程中可以同时做好几件事,如果一个java程序中没有使用多线程,那么程序启动之后,只有main方法所在的线程(主线程)和垃圾收集器的GC线程两个线程。
我们使用多线程,是在main方法这个主线程里面启动其他线程。
默认情况下,main方法里面的代码是从第一行到最后一行按顺序执行的,使用多线程之后,会在开启多线程的地方脱离主线程新开一个分支,执行该线程的代码。
启动一个线程特别简单,实现Runnable接口或者继承Thread
1. 继承Thread
public class App {
public static void main(String[] args) {
Thread t = new MyThread();
t.start(); // 启动新线程
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println("start new thread!");
}
}
2. 实现Runnable
public class Main {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start(); // 启动新线程
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("start new thread!");
}
}
推荐使用实现Runnable的方式
按照上面的方式就能启动一个线程,可以脱离主线程做自己的事。在上面的代码中,new一个Thread之后,线程就创建成功了,执行start就可以启动这个线程,这也引出一个问题:线程有几种状态?
java的Thread类中用一个枚举 State 表达了线程的六种状态:
public enum State {
NEW, // 新创建的线程,尚未执行,如上面的Thread t = new Thread();
RUNNABLE,// 运行中的线程,正在执行run()方法的Java代码;
BLOCKED,// 运行中的线程,因为某些操作被阻塞而挂起;
WAITING,// 运行中的线程,因为某些操作在等待中;
TIMED_WAITING,// 运行中的线程,因为执行sleep()方法正在计时等待;
TERMINATED;// 线程已终止,因为run()方法执行完毕。
}
六种状态中 NEW、RUNNABLE、TERMINATED 比较好理解,其他三个可以理解为:
- BLOCKED 状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态。
- WAITING 状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态。
- TIMED_WAITING 状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒。
六种状态的切换可以参考下图