0%

线程

创建一个线程Thread时,JVM将分配一大块内存到专为线程保留的特殊区域上,用于提供运行任务时所需的一切,包括:

  • 程序计数器,指明要执行的下一个JVM字节码指令

  • 用于支持Java代码执行的栈,包含有关线程已到达当时执行位置所调用方法的信息。它也包含每个正在执行的方法的所有局部变量

  • 第二个则用于native code执行的栈

  • 线程本地变量的存储区域

  • 用于控制线程的状态管理变量

每当调用一个方法时,当前程序计数器被推到该线程的栈上,然后栈指针向下移动以足够来创建一个栈帧,其栈帧里存储该方法的所有局部变量,参数和返回值。所有基本类型变量都直接在栈上,虽然方法中创建对象的任何引用都位于栈帧中,但对象本身存于堆中。

实现Runnable接口比继承Thread的优势

  • 适合多个相同的代码去处理同一个资源

  • 可以避免java单继承的限制

  • 增加程序的健壮性,代码可被多个线程共享,代码和数据独立

方法介绍

  • join() 线程加入进来,要等待该线程执行完在继续执行join之后的代码
  • yield() 暂停当前正在执行的线程,并执行其他线程,大多数情况下yield()方法会进入就绪状态,重新争抢cpu
  • sleep() 在指定的时间内让当前正在执行的线程休眠
  • getState() 获取线程状态
  • wait() Object的wait()方法、notify()、notifyAll()方法必须要与synchronized(obj)一起使用,只能针对已经获取到obj锁的情况,否则会抛出”java.lang.IllegalMonitorStateException“异常

sleep和wait的区别

  • sleep()是Thread的方法,wait()是Object的方法

  • sleep()和wait()虽然都释放CPU,但是如果线程持有对象锁资源的话,sleep()不释放锁资源,wait()释放锁资源,

  • sleep()需要捕获异常,wait()不需要

  • sleep()可以在任意位置使用,wait()必须要在synchronized同步块内使用

Runnable和Callable接口的区别

Runnable中的run()方法返回值为void,Callable中的call方法有返回值且可以抛出异常,可以和Future、FutureTask配合获取异步执行的结果。

自旋锁执行时间短、线程数少的时候使用(由于占用CPU) —–> Atomic和lock都是使用的自旋锁