线程与进程

进程

进程是程序的一次执行过程,系统程序的基本单位。有自己的main方法,并且主要由主方法运行起来的基本上就是进程。

线程

线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享方法区资源,但每个线程有自己的程序计数器虚拟机栈本地方法栈,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

线程创建的方式
  1. 继承 Thread 类,重写 run 方法

  2. 实现 Runnable 接口,重写 run 方法

  3. 实现 Callable 接口,重写 call 方法

    这种形式与实现 Runnable 接口很像,但可以返回一个结果

  4. 线程池创建

之所以要重写 run 方法,是因为 run 方法内根本什么都没有,所以需要重写,赋予具体的功能。

线程的状态
  1. 新建(New):当线程对象被创建但还没有调用start()方法时,线程处于新建状态。在这个状态下,线程还没有开始执行。

  2. 就绪(Runnable):线程调用了start()方法后进入就绪状态。在这个状态下,线程已经准备好运行,等待操作系统分配CPU时间片。

  3. 运行(Running):当线程获得CPU时间片并开始执行时,它进入运行状态。在这个状态下,线程正在执行它的任务。

  4. 阻塞(Blocked):线程在等待某个事件(如I/O操作、获取锁、等待信号量等)时进入阻塞状态。在这个状态下,线程暂时停止执行,直到它等待的事件发生。

  5. 等待(Waiting):线程通过调用wait()join()park()等方法进入等待状态。在这个状态下,线程会无限期地等待,直到另一个线程调用notify()notifyAll()unpark()方法来唤醒它。

  6. 计时等待(Timed Waiting):线程通过调用具有超时参数的方法(如sleep(long)wait(long)join(long)parkNanos()parkUntil())进入计时等待状态。在这个状态下,线程会在指定的时间后自动恢复到就绪状态。

  7. 终止(Terminated):线程完成执行或因异常退出时进入终止状态。在这个状态下,线程不再执行,它的生命周期结束。

线程状态转换

线程的状态可以通过不同的操作进行转换,例如:

  • 从新建状态调用start()方法,线程进入就绪状态。

  • 从就绪状态获得CPU时间片,线程进入运行状态。

  • 从运行状态调用sleep(long)方法,线程进入计时等待状态。

  • 从运行状态调用wait()方法,线程进入等待状态。

  • 从运行状态调用join()方法,线程进入等待状态,等待另一个线程结束。

  • 从运行状态调用park()方法,线程进入等待状态。

  • 从阻塞状态等待的事件发生,线程进入就绪状态。

  • 从等待状态被notify()notifyAll()唤醒,线程进入就绪状态。

  • 从计时等待状态超时,线程进入就绪状态。

  • 从运行状态任务完成或抛出未捕获的异常,线程进入终止状态

当两个线程分别thread.start()时,只是将线程变成了就绪态,不是运行态,所以运行的顺序,还不一定。

wait(),join(),park()的区别
wait

wait()方法是Object类的一部分,因此所有对象都有这个方法。

wait 用于让一个线程进入等待状态,可以做到线程之间的通信,它会释放该对象的锁,并进入等待状态。直到其他线程调用同一个对象的notify()notifyAll()方法来唤醒它。

通常用于生产者-消费者模式中,当生产者生产数据后,生产者调用notify()notifyAll()来唤醒可能正在等待数据的消费者线程。

join

join()方法是Thread类的一部分。

join 用于控制线程之间的顺序。当一个线程调用另一个线程的join()方法时,它会阻塞自己,直到被调用的线程执行完毕。

例子:

public class Main{
    public static void main(String[] args) {
        System.out.println("Main 线程 开始运行!");
         Thread t1 = new Thread(){
             @Override
             public void run(){
                 System.out.println("t1 开始运行!");
                 System.out.println("t1 结束运行!");
             }
         };
         try{
             t1.start();
             t1.join();
         }catch(Exception e){
             
         }
         System.out.println("Main 线程 结束运行!");
    }
}
​
​
/*
Main 线程 开始运行!
t1 开始运行!
t1 结束运行!
Main 线程 结束运行!
*/
park

park()方法是java.util.concurrent.locks.LockSupport类的一部分。

它更自由,park()方法用于暂停当前线程的执行。不需要像 wait 一样,需要持有特定的锁,它直接使用就可以。

线程与进程的关系,区别及优缺点?

图解关系

下图是 Java 内存区域,通过下图我们从 JVM 的角度来说一下线程和进程之间的关系。

Java 运行时数据区域(JDK1.8 之后)

从上图可以看出:一个进程中可以有多个线程,多个线程共享进程的方法区 (JDK1.8 之后的元空间)*资源,但是每个线程有自己的*程序计数器虚拟机栈本地方法栈

总结

线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值