线程的基本概念
进程与线程
进程 进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。 在 Java 中,当我们启动 main 函数时其实就是启动了一个 JVM 的进程,而 main 函数所在的线程就是这个进程中的一个线程,也称主线程。 线程 线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆 和方法区 资源,但每个线程有自己的程序计数器 、虚拟机栈 和本地方法栈 ,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
并发与并行
并发: 同一时间段,多个任务都在执行 (单位时间内不一定同时执行);并行: 单位时间内,多个任务同时执行。
线程的创建方式
方法一:继承Thread类,作为线程对象存在(继承Thread对象)
public class Test extends Thread {
@Override
public void run ( ) {
while ( ! interrupted ( ) ) {
System. out. println ( Thread. currentThread ( ) . getName ( ) + "执行了线程" ) ;
}
}
public static void main ( String[ ] args) {
Test t= new Test ( ) ;
Test t1= new Test ( ) ;
t. start ( ) ;
t1. start ( ) ;
t. interrupt ( ) ;
}
}
方法二:实现runnable接口
public class Test implements Runnable {
@Override
public void run ( ) {
System. out. println ( Thread. currentThread ( ) . getName ( ) + "执行了线程" ) ;
}
public static void main ( String[ ] args) {
Thread t = new Thread ( new Test ( ) ) ;
t. start ( ) ;
}
}
使用匿名内部类方式 lambda和匿名内部来类似
public static void main ( String[ ] args) {
new Thread ( ( ) - > System. out. println ( "执行了线程" ) ) . start ( ) ;
}
方法三:创建带返回值的线程
public class CreatThreadDemo4 implements Callable {
public static void main ( String[ ] args) throws ExecutionException, InterruptedException {
CreatThreadDemo4 demo4 = new CreatThreadDemo4 ( ) ;
FutureTask< Integer> task = new FutureTask < Integer> ( demo4) ;
Thread thread = new Thread ( task) ;
thread. start ( ) ;
System. out. println ( "我可以在这里做点别的业务逻辑...因为FutureTask是提前完成任务" ) ;
Integer result = task. get ( ) ;
System. out. println ( "线程中运算的结果为:" + result) ;
}
@Override
public Object call ( ) throws Exception {
int result = 1 ;
System. out. println ( "业务逻辑计算中..." ) ;
Thread. sleep ( 3000 ) ;
return result;
}
}
线程的状态
**就绪(Runnable)😗*线程准备运行,不一定立马就能开始执行。 **运行中(Running):**进程正在执行线程的代码。 **等待中(Waiting)😗*线程处于阻塞的状态,等待外部的处理结束。 **睡眠中(Sleeping):**线程被强制睡眠。 **I/O阻塞(Blocked on I/O):**等待I/O操作完成。 **同步阻塞(Blocked on Synchronization):**等待获取锁。 **死亡(Dead):**线程完成了执行。
多线程的一些常用方法
start():启动线程 currentThread():获取当前线程对象 getPriority() :获取当前线程的优先级 setPriority(int newPriority): 设置当前线程的优先级(1-10,1代表最低优先级,10代表最高优先级) isAlive() :判断线程是否处于活动状态 (线程调用start后,即处于活动状态) sleep(long millis):线程对象调用sleep(time)方法后,当前线程会等待指定的时间(time),并让出cpu执行权,但是它的监控状态依然当前对象的保持者(不会释放对象锁,休眠的线程会进入阻塞中泰中),当指定的时间到了又会自动恢复运行状态。 interrupt():interrupt()并不能中断在运行中的线程,它只能改变中断状态而已 interrupted:判断当前线程对象的状态是否为中断状态,内部实现是调用的当前线程的isInterrupted(),并且会重置当前线程的中断状态。 isInterrupted:判断当前线程对象的状态是否为中断状态,不会重置当前线程的中断状态 isDaemon( ) :判断是否为守护线程 setDaemon(boolean on):设置为守护线程 join():在A线程中调用了B线程的join()方法时,表示只有当B线程执行完毕时,A线程才能继续执行。并且join()方法是会释放锁的,因为底层使用 wait()
方法来实现的。 yield():放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片(不会释放锁) wait() 使当前线程阻塞,直到调用notify()
,则被唤醒。,wait(long timeOut)
使当前线程阻塞,直到调用notify()
或时长超过timeOut
,则被唤醒。wait会释放锁 notify() / notifyAll():唤醒单个线程/唤醒所有线程 wait()和notify()、notifyAll()方法的调用都必须在synchronized修饰的方法或者代码块中调用,使用过程中必须获得对象锁,否则会抛出java.lang.IllegalMonitorStateException的异常。