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

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

线程的状态

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

线程的常用方法

1、初始化线程

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

private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;
		// 当前线程为父线程
        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
          
            if (security != null) {
                g = security.getThreadGroup();
            }

            if (g == null) {
                g = parent.getThreadGroup();
            }
        }
        g.checkAccess();

        /* * Do we have the required permissions? */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();

        this.group = g;
		//获取父线程的优先级和是否是守护线程
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        //判断是否继承父线程的localmap
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        //分配一个线程号
        tid = nextThreadID();
    }
2、启动线程
/** * 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() */
    public synchronized void start() {
        /** * 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". */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* 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. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */
            }
        }
    }

    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. 如果前面的条件都不成立,那么这个线程的中断状态将被设置。
public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }
    private native void interrupt0();
3.2、interrupted

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

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

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

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

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

@Deprecated
    public final void suspend() {
        checkAccess();
        suspend0();
    }
    
  @Deprecated
  public final void resume() {
        checkAccess();
        resume0();
  }
    
  @Deprecated
  public final void stop() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            checkAccess();
            if (this != Thread.currentThread()) {
                security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
            }
        }
        // A zero status value corresponds to "NEW", it can't change to
        // not-NEW because we hold the lock.
        if (threadStatus != 0) {
            resume(); // Wake up thread if it was suspended; no-op otherwise
        }

        // The VM can handle all thread states
        stop0(new ThreadDeath());
    }
5、join

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

public final synchronized void join(long millis) throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

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

相关文章