进程和线程
进程
- 一个应用程序的实例
- 是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
线程
- 属于进程中的一个执行单元,线程是通过cpu执行的基本单元
- 一个进程中至少有一个主线程存在,主线程可以去申请子线程
cpu执行任务是通过调用进程中的线程
一台电脑中 同时又很多个进程在运行状态
这些进程,又同时有很多个线程在运行状态
单核cpu 同一时间只能调用一个线程
java中一个main方法一个进程,并且开启一个主线程,每个线程有个ID,在java中线程类是Thread类
Thread.currentThread()获取当前线程运行实例对象
Thread.currentThread().getId()获取当前运行的线程ID
JVM启动时就启动了多个线程,至少有两个线程可以分析的出来
- 执行main函数的线程
- 该线程的任务代码都定义在main函数中
- 负责垃圾回收的线程
线程的状态
- 新建状态(New):新创建了一个线程对象。
- 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
- 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
- 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。(wait会释放持有的锁)
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。(注意,sleep是不会释放持有的锁) - 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
创建线程的方法
在java中开启线程有3种方法:
- 继承Thread类
- 实现Runnable接口
- 线程池(这里暂时先不写了)
创建线程方式一:继承Thread类
- 定义一个类继承Thread类
- 覆盖Thead类中的run方法
为什么要覆盖run方法?
创建线程的目的是为了开启一条执行路径,去运行指定的代码和其他代码实现同时运行。
而运行的制定代码就是这个执行路径的任务,jvm创建的主线程的任务都定义在主函数中而自定义的线程它的任务在哪呢?
Thread类用于描述线程,线程是需要任务的,所以Thread类也对任务的描述。
这个任务即使通过Thread类中的run方法来体现,也就是说,run方法就是封装自定义线程运行任务的函数run方法中定义就是线程要运行的任务代码
开启线程是为了运行指定代码,所以只有继承Thread类,并覆盖run方法。将运行的代码定义在run方法中即可
- 直接创建Thread的子类对象,并启动 object.start();
创 大专栏 线程建线程方式二:通过接口的形式完成 Runnable的实现
- 定义类实现 implements Runnable
- 覆盖接口中的run 方法,将线程的任务代码封装到run方法中
- 通过Thread类创建线程对象,并将Runnable接口的子类对象最为Thread类的构造函数的参数进行传递 Thread t1 = new Thread(d);
- 调用线程对象的start方法开启线程 t1.start();
线程中常用方法
Thread.yield( )
- Java线程中的Thread.yield( )方法,译为线程让步。顾名思义,就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,让自己或者其它的线程运行,注意是让自己或者其他线程运行,并不是单纯的让给其他线程。
- yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!
synchronized
- synchronized加在方法前面就是方法锁,作用是保证同一时间只能有一个线程进入该方法执行
- synchronized作用于对象 就是对象锁
- 对象锁是实例方法使用synchronized关键字后,如果是多个线程访问同个对象的sychronized块,是同步的,但是访问不同对象的话还是不同步的。
1 | User user = new User(); |
Object.wait()当前线程睡眠 释放对象锁
Object.notify() 随机唤醒其中一个wait的线程
Object.notifyAll() 唤醒所有wait中的线程
Thread.sleep(20000); 睡眠
wait和sleep的区别:
wait是object类的方法,sleep是Thread类的方法
2个方法都可以让线程暂停运行
但是wait会释放对象锁,sleep不会。
中断:
中断在java中主要有3个方法:interrupt(),sInterrupted()和interrupted()。- interrupt(),在一个线程中调用另一个线程的interrupt()方法,即会向那个线程发出信号——线程中断状态已被设置。至于那个线程何去何从,由具体的代码实现决定。
- isInterrupted(),用来判断当前线程的中断状态(true or false)。
- interrupted()是个Thread的static方法,用来恢复中断状态。
Thread. join();
- join的意思是使得放弃当前线程的执行,并返回对应的线程
- 例如下面代码的意思就是:
程序在main线程中调用t1线程的join方法,则main线程放弃cpu控制权,并返回t1线程继续执行直到线程t1执行完毕
所以结果是t1线程执行完后,才到主线程执行,相当于在main线程中同步t1线程,t1执行完了,main线程才有执行的机会
1 | ThreadJoinTest t1 = new ThreadJoinTest("小明"); |
就这样吧