目录
1.进程和线程
进程(Process):可以看作程序的一次执行过程,是系统运行程序的基本单位
特点:
- 独立性:进程是系统进行资源分配和调度的一个独立单元,各个进程之间互不干扰。
- 动态性:进程是程序的一次执行过程,它有着创建、执行、暂停、终止等状态变化。
- 并发性:多个进程可以在操作系统中并发执行,提高系统的资源利用率和吞吐量。
线程(Thread):进程可以进一步划分为线程,一个进程可以拥有多个线程,这些线程共享进程的资源(如内存、文件句柄等),但每个线程都有自己独立的执行流和堆栈。
特点:
- 轻型性:与进程相比,线程的创建和销毁开销较小,切换速度也更快。
- 共享性:线程间共享进程的内存空间和其他资源,使得线程间的通信更加高效。
- 并发性:多个线程可以在同一进程中并发执行,提高程序的执行效率和响应速度。
2.并行与并发
并行(Parallelism):
并行是指多个程序或任务在同一时刻点,在多个处理器上同时执行。这意味着每个任务都拥有独立的处理器资源,可以真正地同时进行,而不需要等待其他任务完成。
并发(Concurrency):
并发是指在同一时间段内,多个程序或任务都在执行,但并不意味着它们在同一时刻都在执行。
并发是在同一时间段内多个任务交替执行,而并行是在同一时刻点上多个任务同时执行。
3.多线程的实现
1.基础Thread类
创建一个新的类,继承Thread类,并实现run()方法
static class Thread1 extends Thread{
private String name;
public Thread1(String name){
this.name = name;
}
public void run(){
for (int i = 0; i < 3; i++) {
System.out.println(name + i);
try {
//使当前线程暂停300ms,使其他线程运行
sleep(300);
} catch (InterruptedException e) {
//如果在等待过程中被中断,则会抛出异常
throw new RuntimeException(e);
}
}
}
}
public static void main(String[] args) {
//创建两个线程实例
Thread1 thread1 = new Thread1("A");
Thread1 thread2 = new Thread1("B");
//运行
thread1.start();
thread2.start();
}
2.实现Runnable接口
创建一个新的类,实现Runnable接口,并实现run()方法
public static void main(String[] args) {
//创建两个Thread2的实例
Thread2 thread1 = new Thread2("A");
Thread2 thread2 = new Thread2("B");
//创建两个Thread实例,并将上面创建的Thread2的实例作为参数传递给Thread
//每个Thread实例执行Runnable任务中的run方法
Thread thread11 = new Thread(thread1);
Thread thread22 = new Thread(thread2);
thread11.start();
thread22.start();
}
static class Thread2 implements Runnable{
private String name;
public Thread2(String name){
this.name = name;
}
//重写run方法
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(name + i);
try {
sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
4.线程的生命周期
- 新建状态:新创建了一个线程对象
- 就绪状态:线程对象调用了start方法,该线程已具备了运行的条件
- 运行状态:线程获得了时间片时,进入运行状态
- 阻塞状态:在运行过程中,由于某些原因可能会进入阻塞状态,在该状态下,线程将不会进行任何操作,直到该状态解除
- 死亡状态:线程执行完毕,或因异常退出执行,结束生命周期
5.wait和sleep方法的区别
1.唤醒机制:
- wait():在没有设置最大时间的情况下,必须等待其他线程调用同一对象的 notity() 或 notifyAll()方法来唤醒
- sleep():让线程休眠到一定时间后自动继续运行
2.锁机制:
- wait():调用该方法的对象必须持有对象的锁(即必须在同步方法或同步块中调用),调用该方法后会释放对象的锁并进入等待状态
- sleep():只会让进程进行休眠,让出cpu资源,不会释放任何锁
6.start和run方法的区别
1.方法功能:
- start():不会直接执行run()方法,而是使线程进入就绪状态,等待调度
- run():代码逻辑在该方法中实现,当线程执行时,会自动调用该方法
2.执行方式:
- start():创建一个新线程,并在新进程中调用run方法,实现多线程的并发执行
- run():按顺序执行,不会实现多线程的并发
//调用start方法
public static void main(String[] args) {
Thread2 thread1 = new Thread2("A");
Thread2 thread2 = new Thread2("B");
Thread thread11 = new Thread(thread1);
Thread thread22 = new Thread(thread2);
thread11.start();
thread22.start();
}
输出结果:B0 A0 B1 A1 B2 A2
//调用run方法
public static void main(String[] args) {
Thread2 thread1 = new Thread2("A");
Thread2 thread2 = new Thread2("B");
Thread thread11 = new Thread(thread1);
Thread thread22 = new Thread(thread2);
thread11.run();
thread22.run();
}
输出结果:A0 A1 A2 B0 B1 B2