美文网首页java进阶干货程序员Java
Java 多线程(一):多线程基础详解

Java 多线程(一):多线程基础详解

作者: 聪明的奇瑞 | 来源:发表于2018-03-10 11:59 被阅读238次

    多线程概述

    • 多线程是指一个进程(执行中的程序)同时运行多个线程(进程中负责程序执行的执行单元),多线程可以协作完成进程工作,其目的是更好的利用 CPU 资源

    并发与并行

    • 并行:多核多 CPU 或多机器处理同一段处理逻辑的时候,同一时刻多个执行流共同执行
    • 并发:是指通过 CPU 的调度算法,使用户感觉像是再同时处理多个任务,但同一时刻只有一个执行流占用 CPU 执行,即使多核多 CPU 的环境下还是会使用并发,以提高处理效率,主要的调度算法有:
      • 分时调度:每个线程轮流获取 CPU 使用权,各个线程平均 CPU 时间片
      • 抢占式调度:Java 虚拟机使用该调度模型,它会根据线程优先级,先调度优先级高的线程,若线程优先级相同则随机选取线程执行

    并发与并行

    线程终止的四种方式

    • run() 方法执行结束后自然终止
    • 使用 stop() 方法终止
    • 使用 volatile 标志位(外部控制的自然死亡)
    • 使用 interrupt() 方法中断运行状态和阻塞状态线程,interrupt() 方法会改变中断状态,但如果不是在阻塞状态则不会抛出异常,通过 isInterrupt 来作为中断标志推出循环
    • 注意:当线程抛出一个未被捕获的异常或错误时,线程会异常终止

    守护线程

    • 守护线程也称为后台线程,在通过 start() 方法调用前先调用 setDeamon(true) 将线程设置为守护线程
    • 守护线程会在所有前台线程死亡后由 JVM 通知死亡
    • 守护线程最大的应用就是垃圾回收线程,它是一个典型的守护线程

    线程状态

    线程状态
    • 新建状态:创建了线程 Thread 对象就进入了新建状态
    • 就绪状态:调用 start() 方法就会为线程分配私有的方法栈,程序计算器资源,如果得到 CPU 资源就会从就绪状态转为运行状态
    • 运行状态:就绪状态得到 CPU 资源就会转为运行状态,执行 run() 方法,当调用 yield() 时线程会让步,从运行状态转到就绪状态,但该过程可能是及其短暂的,如果当前线程拥有较高优先级,即使让步后还是会进入运行状态
    • 阻塞状态:会导致阻塞状态的方法主要有:sleep()、wait()、join()、等待获取锁、等待 I/O 等情况,在这些情况被处理后就会转为就绪状态,等待调度
    • 终止状态:上述所说的四种线程终止

    基本线程类 Thread 与 Runnable 接口、Callable 接口

    Thread

    • 继承 Thread 并重写其 run() 方法,通过线程对象的 start() 方法来启动线程
    public class Test {
        public static void main(String[] args)  {
            MyThread thread = new MyThread();
            thread.start();
        }
    }
    class MyThread extends Thread{
        private static int num = 0;
        public MyThread(){
            num++;
        }
        @Override
        public void run() {
            System.out.println("主动创建的第"+num+"个线程");
        }
    }
    
    • 方法描述
      • sleep():等待一段时间,但是不释放锁,时间到后进入就绪状态等待调度
      • wait():让线程进入等待状态,同时释放当前线程所持有的锁,直到其它线程调用此对象 notify() 或 notifyAll() 方法后,当前线程会被唤醒,进入就绪状态,等待调度(注意:wait 方法只能在 synchronized 方法里使用)
      • join():把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程,比如在线程 B 中调用了线程 A 的 join() 方法,直到线程 A 执行完毕后才会继续执行线程 B
      • notify() 与 notifyAll():notify 只会通知一个在等待的对象,而 nofityAll() 会通知所有再等待的对象

    Runnable

    • 实现 Runnable 接口需重写 run 方法
    • Runnable 是"任务",通过实现该接口,定义一个任务,然后将子任务交由 Thread 去执行
    public class Test {
        public static void main(String[] args)  {
            System.out.println("主线程ID:"+Thread.currentThread().getId());
            MyRunnable runnable = new MyRunnable();
            Thread thread = new Thread(runnable);
            thread.start();
        }
    } 
    class MyRunnable implements Runnable{
        public MyRunnable() {
        }
    
        @Override
        public void run() {
            System.out.println("子线程ID:"+Thread.currentThread().getId());
        }
    }
    

    Thread 与 Runnable 区别

    • Thread 是线程、而 Runnable 是任务,一个任务可以由多个线程去完成
    • Java 不允许多继承、因此可实现 Runnable 接口在继承其它类

    相关文章

      网友评论

        本文标题:Java 多线程(一):多线程基础详解

        本文链接:https://www.haomeiwen.com/subject/yqwvfftx.html