1.进程与线程
进程:操作系统中一个程序的执行周期为一个进程
线程:一个程序同时执行多个任务,一个任务称之为线程;
线程的优点:
- 创建一个新线程的代价要比创建一个新进程小得多
- 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多
- 线程占用的资源要比进程少很多
- 能充分利用多处理器的可并行数量
- 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
- 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
- I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。
进程与线程的区别
- 进程是系统进行资源分配和调度的一个独立单位,线程是程序执行的最小单位。 一个进程内的线程之间是可以共享资源的。每个进程至少有一个线程存在,即主线程。
- 进程有自己的内存地址空间,线程只独享指令流执行的必要资源,如寄存器和栈。
- 由于同一进程的各线程间共享内存和文件资源,可以不通过内核进行直接通信。
- 线程的创建、切换及终止效率更高。
2.创建线程
方法1-继承 Thread 类
可以通过继承 Thread 来创建一个线程类,该方法的好处是 this 代表的就是当前线程,不需要通过 Thread.currentThread() 来获取当前线程的引用。
class MyThread extends Thread {
@Override
public void run() {
System.out.println("这里是线程运行的代码");
}
}
MyThread t = new MyThread();
t.start(); // 线程开始运行
方法2-实现 Runnable 接口
通过实现 Runnable 接口,并且调用 Thread 的构造方法时将 Runnable 对象作为 target 参数传入来创建线程对象。 该方法的好处是可以规避类的单继承的限制;但需要通过 Thread.currentThread() 来获取当前线程的引用。
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "这里是线程运行的代码");
}
}
Thread t = new Thread(new MyRunnable());
t.start(); // 线程开始运行
其他变形
// 使用匿名类创建 Thread 子类对象
Thread t1 = new Thread() {
@Override
public void run() {
System.out.println("使用匿名类创建 Thread 子类对象");
}
};
// 使用匿名类创建 Runnable 子类对象
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("使用匿名类创建 Runnable 子类对象");
}
});
// 使用 lambda 表达式创建 Runnable 子类对象
Thread t3 = new Thread(() -> System.out.println("使用匿名类创建 Thread 子类对象"));
Thread t4 = new Thread(() -> {
System.out.println("使用匿名类创建 Thread 子类对象");
});
3. 线程的状态
线程的状态是一个枚举类型 Thread.State
public class ThreadState {
public static void main(String[] args) {
for (Thread.State state : Thread.State.values()) {
System.out.println(state);
}
}
}
NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED
关注 NEW 、 RUNNABLE 、 TERMINATED 状态的转换
public class ThreadStateTransfer {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
for (int i = 0; i < 1000_0000; i++) {
}
}, "李四");
System.out.println(t.getName() + ": " + t.getState());;
t.start();
while (t.isAlive()) {
System.out.println(t.getName() + ": " + t.getState());;
}
System.out.println(t.getName() + ": " + t.getState());;
}
}
关注 WAITING 、 BLOCKED 、 TIMED_WAITING 状态的转换
public class ThreadStateTransfer {
public static void main(String[] args) throws InterruptedException {
Object object = new Object();
Thread t = new Thread(() -> {
synchronized (object) {
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 1000_0000; i++) {
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println(t.getState());;
t.start();
System.out.println(t.getState());
Thread.sleep(10);
synchronized (object) {
for (int i = 0; i < 10; i++) {
System.out.println(t.getState());
}
object.notify();
}
while (t.isAlive()) {
System.out.println(t.getState());
}
}
}
yield() 大公无私,让出 CPU
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(() -> {
while (true) {
System.out.println(Thread.currentThread().getName()
+ ": 我跑着呢");
// Thread.yield();
}
}, "李四");
Thread thread2 = new Thread(() -> {
while (true) {
System.out.println(Thread.currentThread().getName()
+ ": 我跑着呢");
}
}, "王五");
thread1.start();
thread2.start();
}
}
yield() 只是让出 CPU,并不会改变自己的状态。