Java并发编程(一)-- 线程

线程是现代操作系统调度的最小执行单元,也有轻量级进程一说。一个进程可包含多个线程,或者说一个进程里可创建多个线程,每个线程都有自己独立的计数器、栈等等信息,并且能够访问共享的堆内存中变量数据。

线程的状态

Java的线程是有生命周期的,在运行过程中处于以下6种状态之一:

状态名称 说明
NEW 初始状态,线程被构建,但是还没有调用start0方法
RUNNABLE 运行状态,Java线程将操作系统中的就绪和运行两种状态笼统地称作“运行中”
BLOCKED 阻塞状态,表示线程阻塞于锁
WAITING 等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程
TIME_WAITING 超时等待状态,该状态不同于WAITING,它是可以在指定的时间自行返回的
TERMINATED 终止状态,表示当前线程已经执行完毕

线程在自身的生命周期里,状态不是固定不变的,而是随着程序的执行在不同的状态间切换,状态变迁图如下:
Java并发编程(一)-- 线程_第1张图片

    注意:Java将操作系统中的运行中状态(RUNNING)和就绪状态(READY)合并成了运行状态(RUNNABLE)。
  • ①:线程创建后,调用start()方法,进入就绪态;
  • ②:调用yield()方法,意味着放手,告诉虚拟机它乐意让其他线程占用自己的位置,并使当前线程进入就绪态;
  • ③:调用对象锁的object.wait()方法,或thread.join()方法,或lockSupport.park()方法时都可使当前线程从运行状态切换至等待状态;
  • ④:与③对应,调用object.notify()/object.notifyAll()/lockSupport.unpark()方法可唤醒在WAITING等待的线程;
  • ⑤:进入超时等待状态,意味着与时间有关,如Thread.sleep(long)方法线程睡眠一段时间、object.wait(long)/thread.join(long)/lockSupport.parkNanos()/lockSupport.parkUntil()等待一段时间;
  • ⑥:从超时等待态重新回到就绪态,可能是唤醒操作如object.notify()/object.notifyAll()/lockSupport.unpark(),也有可能是设定的超时时间到了;
  • ⑦:当线程调用同步方法,如synchronized方法或synchronized块时,在没有获取到锁的情况下,将进入到阻塞状态;
  • ⑧:当线程获取到锁资源后,将回到就绪态。

wait()、join()、yield()、sleep()的区别

wait()

在我的一篇面试题中有提到,wait()方法需要和notify()及notifyAll()一起协同作战,用于多个线程间对共享资源的同步竞争,所以必须在同步块中使用。或者wait(timeout)加超时时间参数,线程释放对象锁,过了指定时间后,重新进入就绪态,抢占锁资源。

join()

join()方法会使当前线程等待调用join()方法的线程结束后才能继续执行,看释义有点绕,看代码:

public class TestJoin {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("main thread start...");
        Thread subThread = new Thread(new SubThread());
        subThread.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("main thread print " + i);
            if (i >= 1) {
                subThread.join();
            }
        }
        System.out.println("main thread end...");
    }
}

class SubThread extends Thread {
    public void run() {
        System.out.println("sub thread start...");
        for (int i = 0; i < 5; i++) {
            System.out.println("sub thread print " + i);
        }
        System.out.println("sub thread end...");
    }
}

运行结果:

main thread start...
main thread print 0
main thread print 1
sub thread start...
sub thread print 0
sub thread print 1
sub thread print 2
sub thread print 3
sub thread print 4
sub thread end...
main thread print 2
main thread print 3
main thread print 4
main thread print 5
main thread print 6
main thread print 7
main thread print 8
main thread print 9
main thread end...

看完代码就豁然开朗了,是不是?

yield()

yield()意思是暂停当前正在执行的线程对象,从线程状态可看出,线程调用了yield()方法后,从运行中状态转换为就绪态,等待系统的调度。有可能的情况是,刚执行完yield()的线程进入到就绪态后,又立马被CPU调度成运行中状态了。
yield()只能使同优先级或更高优先级的线程有执行的机会。

sleep()

让当前正在执行的线程暂停执行多少时间,注意此方法不会释放线程的锁资源,线程进入超时等待状态,直到设定时间到或者被中断(Interrupted),线程重回就绪态。

你可能感兴趣的:(java,Java并发编程进阶)