JAVA多线程的初级认识1--线程的基本认识

  • 为什么要有多线程?

从最开始的真空管穿孔打卡,到后来的晶体管批处理系统,再到后来的集成电路多核并行执行。从硬件资源的级别程度逐渐提高,但是软件如果对硬件资源利用率低,也是一种资源的损耗,所以随之而来的进程和线程应运而生。

为什么有了进程还需要出现线程?

先说一下进程的弊端。

  • 相比进程,对于CPU时间片切换,线程是轻量级的。
  • 仅有单线程无线程的话,如果单个IO阻塞了整个进程,那么程序就会Hang住,从而降低了资源利用率。

而线程是现在cpu执行的最小单位,众所周知,CPU是通过时间片切换来进行类似于并发的效果的。线程的上下文切换的量级远小于线程,从而可以更大程度的利用CPU资源。

  • JAVA的线程状态

其实学习线程状态最好是看看Thread类源码,里面有一个State的Enum类,写几个demo看看~现在截图一下看看Thread源码关于线程状态的注释:

public enum State {
    /**
     * Thread state for a thread which has not yet started.
     */
    NEW,

    /**
     * Thread state for a runnable thread.  A thread in the runnable
     * state is executing in the Java virtual machine but it may
     * be waiting for other resources from the operating system
     * such as processor.
     */
    RUNNABLE,

    /**
     * Thread state for a thread blocked waiting for a monitor lock.
     * A thread in the blocked state is waiting for a monitor lock
     * to enter a synchronized block/method or
     * reenter a synchronized block/method after calling
     * {@link Object#wait() Object.wait}.
     */
    BLOCKED,

    /**
     * Thread state for a waiting thread.
     * A thread is in the waiting state due to calling one of the
     * following methods:
     * <ul>
     *   <li>{@link Object#wait() Object.wait} with no timeout</li>
     *   <li>{@link #join() Thread.join} with no timeout</li>
     *   <li>{@link LockSupport#park() LockSupport.park}</li>
     * </ul>
     *
     * <p>A thread in the waiting state is waiting for another thread to
     * perform a particular action.
     *
     * For example, a thread that has called <tt>Object.wait()</tt>
     * on an object is waiting for another thread to call
     * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
     * that object. A thread that has called <tt>Thread.join()</tt>
     * is waiting for a specified thread to terminate.
     */
    WAITING,

    /**
     * Thread state for a waiting thread with a specified waiting time.
     * A thread is in the timed waiting state due to calling one of
     * the following methods with a specified positive waiting time:
     * <ul>
     *   <li>{@link #sleep Thread.sleep}</li>
     *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
     *   <li>{@link #join(long) Thread.join} with timeout</li>
     *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
     *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
     * </ul>
     */
    TIMED_WAITING,

    /**
     * Thread state for a terminated thread.
     * The thread has completed execution.
     */
    TERMINATED;
}

一共6种状态,具体的转换图如下:

JAVA多线程的初级认识1--线程的基本认识

查看线程状态可以使用JDK提供的工具来进行辅助~包括JPS,JSTACK。

JPS获取java进程号。

JSTACK可以获取线程堆栈的具体信息

 

  • 线程的启动和销毁

线程的启动,不考虑Callable和Future的前提下,只考虑Thread和Runnable。我们看Thread的源码,我们都是通过调用Start方法而非run方法来启动线程的。

start方法查看进去,会调用一个start0的native方法。该方法我们就看不到了,因为是cpp源码,我们可以找到http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/00cd9dc3c2b5/src/share/native/java/lang/Thread.c 来看具体的Thread的源码~然后一步一步对应,通过start0-->jvm.cpp里面的JVM_Start_Thread-->thread.cpp里面的Thread.Java_thread和Start(需要下载hotspot源码)-->Thread.start里面会调用run方法

 

线程的销毁

Thread提供了stop和suspend方法,但是都已经过时,其实想想也很正确,A线程调用B线程的stop方法,本身就是一个很奇怪的事情。Thread提供了一个interrupt函数来优雅的中断一个线程。看源码又会走到c++源码中,具体细节不多讲了,结果能就是有一个volatile的interrupted的变量变成true,然后呢告知线程,有人向中断你,仅此而已,至于会不会被中断,是线程自己的事情。简单来说就是:

A想中断B线程,就调用B线程interrupt方法,然后B线程的interrupted boolean变量设置为true,B线程收到中断信号,如果不想处理,直接不理这个信号就好,然后调用Thread.interrupted方法来对interrupted变量进行复位。

Thread提供一种IsInterrupted方法来判断线程是否被中断。