一、程序、进程、线程

程序


    为了解决某个问题、实现某个功能用某种编程语言编写的代码文件,是静态的;(例如在本地未运行的各种应用程序QQ、微信等);

进程


    当程序被运行,程序由静态变为动态,就会产生相应的进程,是动态的,有生命周期;(例如打开QQ程序,就会有QQ的进程);

线程


    是程序的一次执行过程,每一个线程便是做一件任务的一条通道。一个Java程序至少有三个线程,即主线程、垃圾回收线程、异常处理线程;在未使用多线程时,我们写的所有代码都在主线程中执行。

二、单线程与多线程区别


    单线程就是同一时间只能做一件事,而多线程则是同时可以做多件事;例如你在吃饭时来了电话,如果饭局很重要,你只能先吃了饭在打电话,那就是单线程,只能做一件事;如果饭局很随意,你可以一边吃饭一边打电话,同时完成了两件事,就是多线程。

三、何时使用多线程


    1、程序需要同时执行多个任务时;
    2、程序中有需要等待的任务,例如用户输入、文件读写、网络操作等;
    3、需要后台运行;

四、线程的分类


    Java线程分为两类:守护线程和用户线程;其实两类线程的唯一区别就是判断JVM何时退出,其他没有区别,其中守护线程是用来服务用户线程的,可以通过在start()方法之前调用thread.setDaemon(true)将用户线程设置为守护线程垃圾回收线程就是守护线程,若JVM中全是守护线程,则当前JVM退出。

五、线程的创建和启用

Thread类的概述

Thraed特性


    1、每个线程都是通过某个Thread()对象的run()方法完成操作,经常将run()方法的方法体称为线程体。
    2、通过调用start()方法启用线程,而不是调用run()方法。

Thraed构造器


    Thread():创建新的Thread对象
    Thread(String threadname): 创建线程并指定线程实例名
    Thread(Runnable target): 指定创建线程的目标对象,它实现了Runnable接口中的run方法
    Thread(Runnable target, String name): 创建新的Thread对象

Thraed常用方法


    void start(): 启动线程,并执行对象的run()方法
    run(): 线程在被调度时执行的操作
    String getName(): 返回线程的名称
    void setName(String name):设置该线程名称
    static Thread currentThread(): 返回当前线程。在Thread子类中就是this,通常用于主线程和Runnable实现类
    static void yield(): 线程让步
    暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程
    若队列中没有同优先级的线程,忽略此方法
    join() : 当某个程序执行流中调用其他线程的 join() 方法时, 调用线程将被阻塞,直到 join() 方法加入的 join 线程执行完为止低优先级的线程也可以获得执行
    static void sleep(long millis): (指定时间:毫秒)令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排队。
    stop(): 强制线程生命期结束,不推荐使用
    boolean isAlive(): 返回boolean,判断线程是否还活着

方式一:继承Thread

步骤


    1、定义子类继承Thread;
    2、重写run()方法;
    3、创建子类对象;
    4、调用start()方法启用线程;

代码


    Thread1类

public class Thread1 extends Thread{ @Override public void run() { System.out.println("新线程"); } }

    Test类

public class Test { public static void main(String[] args) { // 1、定义子类继承Thread; // 2、子类中重写run() 方法; // 3、创建子类对象; Thread1 t1 = new Thread1(); // 4、调用start() 方法启用线程; t1.start(); } }

方式二:实现Runnable

步骤


    1、定义子类实现Runnable;
    2、子类中重写run()方法;
    3、创建子类对象;
    4、通过Thread含参构造方法创建Thread对象;
    5、调用start()方法启用线程;

代码


    Thread1类

public class Thread1 implements Runnable{ @Override public void run() { System.out.println("新线程"); } }

    Test类

public class Test { public static void main(String[] args) { // 1、定义子类实现Runnable; // 2、子类中重写run() 方法; // 3、创建子类对象; Thread1 thread1 = new Thread1(); // 4、通过Thread含参构造方法创建Thread对象; Thread thread = new Thread(thread1); // 5、调用start() 方法启用线程; thread.start(); } }

六、实现和继承对比

不同之处


    1、继承只能单继承,而实现没有这一重限制;
    2、实现时,多个线程可共享同一个接口实现类的对象;

相同之处


    1、手动调用run()方法只是普通调用,并未启用多线程;
    2、run()方法调用的一切控制由cpu决定;
    3、要想启用多线程,必须调用start()方法;
    4、一个线程只能调用一次start()方法,否则会报异常;

七、线程优先级

Java线程调度方法


    同优先级线程组成先进先出队列(先到先服务),使用时间片策略;
    对高优先级,使用优先调度的抢占式策略,抢占式即高优先级线程抢占CPU资源;

线程的优先级等级


    MAX_PRIORITY: 10
    MIN _PRIORITY: 1
    NORM_PRIORITY: 5

涉及的方法

    getPriority() : 返回线程优先值
    setPriority(int newPriority) : 改变线程的优先级

说明

    线程创建时继承父线程的优先级
    低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用

八、线程生命周期

五种状态


    新建:当一个线程被创建时,处于新建状态;
    就绪:当线程调用start()方法后,表示该线程被启用,可以被调度,但是未获得CPU资源,所以未被调用;
    运行:当就绪的线程获得时间片后,进入运行状态,开始执行run方法,若时间片用完后run()方法未执行完,则回到就绪状态,继续争夺时间片,若再次争夺到时间片,则接着上次执行的地方开始执行,直到执行完run()方法;
    阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出 CPU 并临时中
止自己的执行,进入阻塞状态;
    死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束;


    后续在本文章继续更新。。。。。。。。。。

版权声明:本文为yblBlog原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/yblBlog/p/13381394.html