1. 多线程基础
操作系统对CPU采用时间切片的方式轮流让多个任务交替运行,由于每个片的时间很短,所以在人看来,CPU就是在同时进行多个任务。
上述中的一个任务实际上就是一个进程
,但有时某些进程还需要执行多个子任务,比如在网络编程中,服务器的套接字等待接收客户端的数据时,还要处理其他逻辑,这里的子任务称为线程
。
一个进程可以包含多个线程,但至少包含一个主线程。
一个Java程序实际上就是一个JVM进程,JVM进程用一个主线程来执行main()
方法,在main()
方法中,又可以创建多个线程。由于Java具有垃圾回收机制,所以这个进程还包括垃圾回收线程以及其他工作线程。
2. 创建新线程
在Java中创建一个新线程非常容易,首先需要实例化一个Thread
实例,然后调用它的start()
方法。
public class Main {
public static void main(String[] args) {
Thread t = new Thread();
t.start();
}
}
但是这个线程启动后什么都不做就立即结束了,要想新线程能做一点事情,我们需要重写run()
方法,有以下几种方法。
方法一:定义一个继承Thread
的类,并重写run()
方法。
public class Main {
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!");
}
}
方法二:创建Thread
实例时,传入一个实现了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!");
}
}
方法三:创建Thread
实例时,定义一个匿名类,并重写run()
方法。
public class Main {
public static void main(String[] args) {
Thread t = new Thread() {
@Override
public void run() {
System.out.println("Start new thread!");
}
};
t.start();
}
}
方法四:创建Thread
实例时,传入一个lambda。
public class Main {
public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("Start new thread!");
});
}
}
小结摘抄:
- Java用
Thread
对象表示一个新线程,通过调用start()
启动一个新线程。 - 一个线程只能调用一次
start()
方法。 - 线程的执行代码写在
run()
方法中。 - 线程的调度由操作系统决定,程序本身无法决定调度顺序。
Thread.sleep()
可以把当前线程暂停一段时间。
3. 线程的状态
Java线程的状态有以下几种:
- New:新创建的线程,但尚未调用
start()
方法。 - Runnable:在Java虚拟机中运行的线程,也就是正在运行
run()
方法。 - Blocked:在Java虚拟机中运行的线程,但由于某些操作而被阻塞。
- Waiting:在Java虚拟机中运行的线程,但由于某些操作而在等待。
- Timed Waiting:在Java虚拟机中运行的线程,执行了
sleep()
方法且正在计时。 - Terminated:线程已终止,
run()
方法执行完毕。
线程终止的原因有:
- 线程正常终止:
run()
方法执行到return
语句返回。 - 线程意外终止:
run()
方法因为未捕获异常导致线程终止。 - 对某个线程的
Thread
实例调用stop()
方法强制终止。(强烈不推荐)
同时我们还可以调用线程实例的join()
,来等待这个线程运行结束后再运行。
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
System.out.println("running");
});
System.out.println("start");
t.start();
t.join();
System.out.println("end");
}
}
恒定输出顺序:
start
running
end