并发编程篇:进程状态的那些知识点,你还记得吗?

x33g5p2x  于2021-12-18 转载在 其他  
字(4.8k)|赞(0)|评价(0)|浏览(438)

线程的状态

常见的线程状态
  1. 初始状态(NEW):线程被构建,没有调用start方法
  2. 运行状态(RUNNABLE):JAVA线程将操作系统中的就绪和运行两中状态统称为“运行中”
  3. 阻塞状态(blocked):线程阻塞于锁
  4. 等待状态(WAITING):当前线程需要等待其他线程做出一些特定动作(通知或者中断)
  5. 超时等待状态(TIME_WAITING):不同于WAITING,可以在制定时间返回
  6. 终止状态(TERMINTED):当前线程已经执行完毕
状态的流转

线程的常用方法

1、初始化线程

初始化一个线程,由父线程进行空间分配,子线程继承了父线程的daemon、priority,以及可以继承的ThreadLocal,同时分配一个唯一的标识的线程id

  1. private void init(ThreadGroup g, Runnable target, String name,
  2. long stackSize, AccessControlContext acc,
  3. boolean inheritThreadLocals) {
  4. if (name == null) {
  5. throw new NullPointerException("name cannot be null");
  6. }
  7. this.name = name;
  8. // 当前线程为父线程
  9. Thread parent = currentThread();
  10. SecurityManager security = System.getSecurityManager();
  11. if (g == null) {
  12. if (security != null) {
  13. g = security.getThreadGroup();
  14. }
  15. if (g == null) {
  16. g = parent.getThreadGroup();
  17. }
  18. }
  19. g.checkAccess();
  20. /* * Do we have the required permissions? */
  21. if (security != null) {
  22. if (isCCLOverridden(getClass())) {
  23. security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  24. }
  25. }
  26. g.addUnstarted();
  27. this.group = g;
  28. //获取父线程的优先级和是否是守护线程
  29. this.daemon = parent.isDaemon();
  30. this.priority = parent.getPriority();
  31. if (security == null || isCCLOverridden(parent.getClass()))
  32. this.contextClassLoader = parent.getContextClassLoader();
  33. else
  34. this.contextClassLoader = parent.contextClassLoader;
  35. this.inheritedAccessControlContext =
  36. acc != null ? acc : AccessController.getContext();
  37. this.target = target;
  38. setPriority(priority);
  39. //判断是否继承父线程的localmap
  40. if (inheritThreadLocals && parent.inheritableThreadLocals != null)
  41. this.inheritableThreadLocals =
  42. ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
  43. /* Stash the specified stack size in case the VM cares */
  44. this.stackSize = stackSize;
  45. //分配一个线程号
  46. tid = nextThreadID();
  47. }
2、启动线程
  1. /** * Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread. * The result is that two threads are running concurrently: the current thread (which returns from the call to the * start() method) and the other thread (which executes its run() method). * It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has * completed execution. * * @exception IllegalThreadStateException if the thread was already * started. * @see #run() * @see #stop() */
  2. public synchronized void start() {
  3. /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */
  4. if (threadStatus != 0)
  5. throw new IllegalThreadStateException();
  6. /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */
  7. group.add(this);
  8. boolean started = false;
  9. try {
  10. start0();
  11. started = true;
  12. } finally {
  13. try {
  14. if (!started) {
  15. group.threadStartFailed(this);
  16. }
  17. } catch (Throwable ignore) {
  18. /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */
  19. }
  20. }
  21. }
  22. private native void start0();
3、中断
3.1、interrupt
  1. 除非当前线程正在中断自己(这总是允许的),否则将调用该线程的checkAccess方法,这可能导致抛出SecurityException。
  2. 如果当前线程被blocked,再调用 the wait(), wait(long), or wait(long, int)methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long,int),interrupt(),中断标识被清除,同时抛出InterruptedException
  3. 如果这个线程在I/O操作中被InterruptibleChannel阻塞,那么通道将被关闭,线程的中断状态将被设置,并且该线程将接收到一个java.nio.channels.ClosedByInterruptException。
  4. 如果这个线程在java.nio.channels中被阻塞。然后线程的中断状态将被设置,它将立即从选择操作中返回,可能带有一个非零值,就像调用了选择器的唤醒方法一样。
  5. 如果前面的条件都不成立,那么这个线程的中断状态将被设置。
  1. public void interrupt() {
  2. if (this != Thread.currentThread())
  3. checkAccess();
  4. synchronized (blockerLock) {
  5. Interruptible b = blocker;
  6. if (b != null) {
  7. interrupt0(); // Just to set the interrupt flag
  8. b.interrupt(this);
  9. return;
  10. }
  11. }
  12. interrupt0();
  13. }
  14. private native void interrupt0();
3.2、interrupted

返回当前线程是否被中断过,并当前线程的中断标识进行复位。

  1. public static boolean interrupted() {
  2. return currentThread().isInterrupted(true);
  3. }
  4. private native boolean isInterrupted(boolean ClearInterrupted);
3.3 isInterrupted

返回当前线程是否被中断过

  1. public boolean isInterrupted() {
  2. return isInterrupted(false);
  3. }
4、暂停suspend、恢复resume、终止stop

调用了suspend方法后,线程不会释放已经占有的资源,容易引起死锁;同样,stop方法也不保证释放所有的资源正常释放

  1. @Deprecated
  2. public final void suspend() {
  3. checkAccess();
  4. suspend0();
  5. }
  6. @Deprecated
  7. public final void resume() {
  8. checkAccess();
  9. resume0();
  10. }
  11. @Deprecated
  12. public final void stop() {
  13. SecurityManager security = System.getSecurityManager();
  14. if (security != null) {
  15. checkAccess();
  16. if (this != Thread.currentThread()) {
  17. security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
  18. }
  19. }
  20. // A zero status value corresponds to "NEW", it can't change to
  21. // not-NEW because we hold the lock.
  22. if (threadStatus != 0) {
  23. resume(); // Wake up thread if it was suspended; no-op otherwise
  24. }
  25. // The VM can handle all thread states
  26. stop0(new ThreadDeath());
  27. }
5、join

等待线程死亡的时间最多为毫秒。超时为0意味着永远等待。

  1. public final synchronized void join(long millis) throws InterruptedException {
  2. long base = System.currentTimeMillis();
  3. long now = 0;
  4. if (millis < 0) {
  5. throw new IllegalArgumentException("timeout value is negative");
  6. }
  7. if (millis == 0) {
  8. while (isAlive()) {
  9. wait(0);
  10. }
  11. } else {
  12. while (isAlive()) {
  13. long delay = millis - now;
  14. if (delay <= 0) {
  15. break;
  16. }
  17. wait(delay);
  18. now = System.currentTimeMillis() - base;
  19. }
  20. }
  21. }

关于面试哪些事,欢迎关注公众号“程序员ZZ的源码”

相关文章