JAVA多线程编程学习(1)

该博客主要内容是根据《JAVA多线程编程实战指南核心篇 》第一章内容进行阅读所做的笔记。

进程的定义:

一个java程序的实质是启动一个java虚拟机进程,或者说一个运行的java程序是java虚拟机进程。
一个java程序所创建的进程在Linux 下可以用 如下命令进行查看
Ps –ef | grep “main类名” | grep –v “grep”
(该命令的作用是查找启动命令中包含字符串“main类名”的进程)
进程(process)是程序向操作系统申请资源(如内存空间和文件句柄)的基本单位。

线程的定义:
线程(thread)是进程中可独立执行的最小单位。一个进程可包含多个线程。同一个进程中所有线程共享该进程中的资源(如内存空间、文件句柄)
任务是线程索要完成的计算。即线程所需要完成的工作。

Java是一门面向对象的编程语言以类(Class)为基本的抽象单位,而多线程编程中以线程为基本的抽象单位。多线程编程和面向对象编程可以相容的,即在面向对象编程的基础上实现多线程编。事实上,JAVA平台中的一个线程就是一个对象。
使用多线程编程在增加线程时可能会增加单位时间内完成的任务量,即提高程序的计算效率,但也可能会降低计算效率。如何创建线程:
Java.lang.Thread
Thread两个常用的构造器:Thread() 和 Thread(Runnable target)
Thread类实际上是Runnable接口的一个实现类。  
所以创建线程的方法有两种:第一中是通过继承Thread类,重写父类的run方法;
第二种是创建一个java.lang.Runnable接口的实例并实现run方法,然后以该接口的实例做为构造器的参数直接创建。代码如下:

public class mainTest {
    public static void main(String[] args){
        /**
         * 采用继承Thread类重写了run 方法 创建线程
         */
        Thread extendsThreadTest = new ExtendsThreadTest();

        /**
         * 实现Runnable接口,实现了run 方法 创建线程
         */
        Thread implentRunnable = new Thread(new ImplentRunnaleTest());
        //启动线程
        extendsThreadTest.start();
        implentRunnable.start();
        System.out.println("1.线程的名字是"+Thread.currentThread().getName());
    }
}
  
 
public class ExtendsThreadTest extends Thread {

    /**
     * 重写父类的run方法
     */
    @Override
    public void run(){
        System.out.println("2.当前线程是"+Thread.currentThread().getName());
    }
}
public class ImplentRunnaleTest implements Runnable {
    /**
     * 实现Runnable的run方法
     */
    @Override
    public void run() {
        System.out.println("3.当前线程的名字是"+Thread.currentThread().getName());
    }
}

上述代码中,run方法相当于线程的处理逻辑的入口方法,它由JAVA虚拟机在运行相应线程时直接调用。
start()方法作用是启动相应的线程。启动一个线程的实质是请求Java虚拟机运行相应的线程,而这个线程具体合适能够运行室友线程调度器(Scheduler)决定的。因此Start方法调用结束并不意味着相应线程已经开始运行。
若线程不是通过start方法启动,而是直接在主线程下调用run方法,那该线程输入主线线程。

在JAVA平台中,一个线程就是一个对象,对象的创建离不开内存空间的分配。创建一个线程与创建其他类型的JAVA对象所不同的是,Java虚拟机会为每个线程分配调用栈(Call Stack)所需的内存空间。调用栈用于跟踪JAVA代码(方法)间的调用关系以及java代码对本地代码(C代码)的调用。另外,Java平台中的每个线程可能还有一个内核线程(具体与JAVA虚拟机的实现有关)与之对应。因此相对来说,创建线程对象比创建其他类型的对象的成本要高一些。

摘自《java多线程编程实战指南》
JAVA多线程编程学习(1)_第1张图片

 

线程的属性包括:编号,名称,类别,优先级
 JAVA多线程编程学习(1)_第2张图片


守护线程是指重要性不是很高,不会阻止JAVA虚拟机正常停止的线程。
用户线程会组织JAVA虚拟机正常停止。
(Java虚拟机正常停止指不是通过System.exit 调用也不是通过终止进程(如在linux系统下使用kill命令停止java进程)实现的java虚拟机停止)。
线程中的父子关系就被称为线程的层次关系。一个线程是否是守护线程默认取决于其父线程。另外,父线程在创建子线程后启动子线程之前可以调用该线程的setDaemon方法,将相应的线程设置为守护线程(或用户线程)。
父线程与子线程之间的生命周期没有必然的联系。
习惯上,也称某些子线程为工作者线程(Worker Thread)或者后台线程(Background Thread)。工作者线程通常是其父类线程创建来用于专门负责某项特定任务的执行的。DoGet方法对请求进行处理的线程通常被称为Web服务器的工作者线程。Java虚拟机中对内存进行回收的线程通常被称为GC(Garbage Collection)工作者线程。

Thread类的常用方法:
JAVA多线程编程学习(1)_第3张图片

Thread 一些废弃的方法:
 JAVA多线程编程学习(1)_第4张图片
线程的生命周期:
   JAVA多线程编程学习(1)_第5张图片

Java线程的状态可以使用监控工具查看,或使用 Thread.getState()调用来获取。
Thread.getState()的返回类型是枚举类(Eunm)状态包括:
1.  NEW:一个已创建而未启动的线程处于该状态。由于一个线程实例只能够被启动一次,因此一个线程只可能有一次处于该状态。
2.  RUNNABLE:该状态可以被看成一个复合状态。包含两个子状态:READY和RUNNING。前者表示处于该状态的线程可以被线程调度器(Scheduler),后者处于该状态的线程正在运行。
3.  BLOCKED:一个线程发起一个阻塞,处于BLOCKED状态的线程并不会占用处理器资源。
4.  WAITING:通过Object.wait()、Thread.join()和LockSupport.park(Object)使线程处于这个状态。通过Object.notify/Object.notifyAll()和LockSupport.unpark(Object)从WAITING变更成RUNNABLE
5.  TIMED_WAITING:与WAITING类型相似,差别在于处于该状态的线程并非无线制地等待其他线程执行指定的操作,而是处于带有时间限制的等待状态。
6.  TERMINARED: 已经执行结束的线程处于该状态。由于一个线程实例只能够被启动一次,因此一个线程也只可能有一次处于该状态。

一个线程在其整个生命周期中,只可能有一次处于NEW状态和TERMINATED状态
    
对线程进行监视的主要途径是获取并查看程序的线程转储(Thread Dump)。一个程序的线程转储包含了获取这个线程转储的那一刻该程序的线程信息。包括:线程的属性(ID、名称、优先级等)、生命周期状态、线程的调用栈(Call Stack)以及锁。如下图:
JAVA多线程编程学习(1)_第6张图片

 JAVA多线程编程学习(1)_第7张图片
    

你可能感兴趣的:(java多线程)