Una comprensión simple de ava thread Thread

      En el artículo anterior, se mencionó un método clave de unión de subprocesos y el estado del subproceso de subproceso. Estos son los contenidos del código de subproceso. Hoy, echemos un vistazo a subproceso nuevamente.

      Se puede decir que la clase Thread es una de las clases más importantes del JDK. Siempre que use asincronía, bloqueos, esperas, etc., no puede prescindir de Thread. Incluso si inicia un método principal, necesita para usar la clase Thread en segundo plano. Para comprender esta clase, todavía tenemos que comenzar con su método de construcción. Veamos el método de construcción de Thread.

  /*无参构造方法*/
 public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }

  /*Runnable入参构造方法*/
 public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

 /*ThreadGroup ,Runnable入参构造方法*/
 public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
    }

 /*线程名称入参构造方法*/
 public Thread(String name) {
        init(null, null, name, 0);
    }
/*ThreadGroup ,线程名称入参构造方法*/
 public Thread(ThreadGroup group, String name) {
        init(group, null, name, 0);
    }

/*Runnable ,线程名称入参构造方法*/
 public Thread(Runnable target, String name) {
        init(null, target, name, 0);
    }
/*ThreadGroup ,Runnable ,线程名称入参构造方法*/
public Thread(ThreadGroup group, Runnable target, String name) {
        init(group, target, name, 0);
    }

/*ThreadGroup ,Runnable ,线程名称,预期堆栈大小 入参构造方法*/
public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
        init(group, target, name, stackSize);
    }

       Hay muchos métodos de construcción de subprocesos, pero puede encontrar que todos los métodos de construcción apuntan al método init, ¡y el método de construcción de subprocesos se implementa realmente a través del método init! En general, no se recomienda ocuparse de la lógica en el método de construcción. Por supuesto, si eres más competente en este aspecto, también puedes hacerlo, ^ _ ^.

       Veamos el método init. Hay muchas cosas involucradas en el método, como los permisos, los grupos de subprocesos, el orden de ejecución e incluso la cantidad de memoria que ocupa el subproceso, pero para nosotros, generalmente se utilizan los tres nombres de subproceso, la identificación del subproceso y la ejecución del subproceso. (Ejecutable) más el estado del hilo (* ^ ▽ ^ *)

 // Thread 初始化方法
 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是一个允许应用实现一种安全策略的类,它允许一个应用去明确,在执行一个可能
		//安全或者敏感的操作之前,此操作是否允许在一个安全的上下文中执行。应用可以统一或者拒绝执行
		//操作。
        SecurityManager security = System.getSecurityManager();
		//线程组为空
        if (g == null) {
            //管理策略不为空,就是去从security中获取当前线程的线程组
            if (security != null) {
                g = security.getThreadGroup();
            }
			// security没有赋值group,那么久直接使用parent的ThreadGroup
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

        //判断线程组是否允许操作(这个源码有点多,就不深入了)
        g.checkAccess();

        /*
         * security 不为空的话,检验Class的管理策略
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

		//把线程加入到ThreadGroup组里。
        g.addUnstarted();
		//线程组
        this.group = g;
		//是否是守护线程
        this.daemon = parent.isDaemon();
		//优先级,默认是5,数字越大越先执行,从0开始
        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);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        //给线程分配的栈大小,这个一般是默认的
        this.stackSize = stackSize;

        //线程ID
        tid = nextThreadID();
    }

Esta es una explicación del método init, y no entraré en detalles, porque hay muchas cosas involucradas. Vamos a mostrar los atributos de Thread a continuación, para que todos puedan familiarizarse con los hilos lo antes posible.

//线程名字
private volatile String name;
//优先级
private int            priority;
// 内置的一个线程Thread类
private Thread         threadQ;
//JVM中的JavaThread指针
private long           eetop;

// 是否单步执行此线程 
private boolean     single_step;

// 是否是守护线程 
private boolean     daemon = false;

// 虚拟机状态 
private boolean     stillborn = false;

// 传进来的对象 
private Runnable target;

// 线程的组 
private ThreadGroup group;

// 线程的上下文加载器,可以用来加载一些资源 
private ClassLoader contextClassLoader;

// 继承的访问控制上下文 
private AccessControlContext inheritedAccessControlContext;

// 给匿名线程命名的整数,匿名线程会被命名为Thread-1这类名字,这个int会自增 
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
    return threadInitNumber++;
}

//ThreadLocal的Map用于保存变量副本,不了解的话可以看下之前关于ThreadLocal的讲解 
ThreadLocal.ThreadLocalMap threadLocals = null;

// InheritableThreadLocal用于子线程能够拿到父线程往ThreadLocal里设置的值 
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

//给线程分配的栈大小
private long stackSize;

// 本地线程终止之后的专用状态
private long nativeParkEventPointer;

// 线程ID
private long tid;

// 用于生成线程ID 
private static long threadSeqNumber;

// 线程状态 
private volatile int threadStatus = 0;

Lo siguiente trata principalmente sobre el estado de unión y subproceso, y muchos otros son métodos nativos, que no son fáciles de analizar.

        Aquí hablaré sobre unirse, podemos ver el método de unión.

  public final synchronized void join(long millis, int nanos)
    throws InterruptedException{
       // 略

    }

       Se modifica con sincronizado, por lo que una vez que un hilo (hilo1) llama al método de unión, es equivalente a que el método de unión adquiera el bloqueo del monitor. La lógica dentro del bloqueo no se ha ejecutado y la lógica del método principal no se puede ejecutar. Este es el método de combinación que se puede ejecutar antes de tiempo.

  while (isAlive()) {
                wait(0);
            }

Se puede ver que hay un método de espera en el método de unión, por lo que, dado que hay un método de espera que finalmente se ejecuta, debe despertarse para la operación de activación. Después de todo, thread1 se está ejecutando en el subproceso principal. Si Dejas el hilo principal hacia abajo, luego el hilo principal regañará a N. Aquí está la explicación de los grandes debajo de la copia.

//一个c++函数:
void JavaThread::exit(bool destroy_vm, ExitType exit_type) ;

//这家伙是啥,就是一个线程执行完毕之后,jvm会做的事,做清理啊收尾工作,
//里面有一个贼不起眼的一行代码,眼神不好还看不到的呢,就是这个:

ensure_join(this);

//翻译成中文叫 确保_join(这个);代码如下:

static void ensure_join(JavaThread* thread) {
  Handle threadObj(thread, thread->threadObj());

  ObjectLocker lock(threadObj, thread);

  thread->clear_pending_exception();

  java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);

  java_lang_Thread::set_thread(threadObj(), NULL);

  //同志们看到了没,别的不用看,就看这一句,
//thread就是当前线程
  lock.notify_all(thread);

  thread->clear_pending_exception();
}

// 链接:https://www.zhihu.com/question/44621343/answer/97640972

       Aquí puede ver que hay una operación de activación de subprocesos en el código fuente de la JVM, es decir, se ejecuta thread1, se debe notificar a All, y luego reactivar el subproceso principal, de lo contrario la lógica se bloqueará, O (∩_ ∩) Oh jaja ~

Sin sacrificio, sin victoria ~

Supongo que te gusta

Origin blog.csdn.net/zsah2011/article/details/109479249
Recomendado
Clasificación