Java-多线程总结

Java-多线程总结

1.1 基本概念

1.1.1 程序、进程、线程

  • 程序:存放在硬盘中的可执行软件
  • 进程:程序读取至内存中启动 --资源分配的基本单位
  • 线程:程序执行的基本单位

1.1.2 并发、并行、多进程、多线程

  • 并发:在一段时间内多个任务同时执行,或者说是在一段很短的时间内可以执行多条程序指令,微观上看起来好像是可以同时运行多个进程,单核处理器就可以做到。
  • 并行:在同一时刻多个任务同时执行,或者说是在同一时刻可以执行多条程序指令,多核处理器才可以做到。
  • 多进程:每个进程都拥有自己独立的资源,多个进程可在单核处理器上并发执行,在多核处理器上并行执行。
  • 多线程:一个进程可由多个线程组成,多个线程共享进程内资源,多个线程可在单核处理器上并发执行,在多核处理器并行执行。

1.1.3 程序运行过程

程序是如何开始运行的?

  • 将程序读取至内存中
  • CPU通过IO将内存中的指令读取至PC,将数据读取至Registers中,并在ALU数据逻辑单元中进行运算,最后再通过IO回写数据至内存中
  • 若内存中存在多个线程,操作系统可以控制当前执行线程,PC可以保存当前执行进度至cache中,多个线程交替占用CPU资源。
    在这里插入图片描述

1.2 线程的生命周期

  • 新建 :从新建一个线程对象到程序start() 这个线程之间的状态,都是新建状态;
  • 就绪 :线程对象调用start()方法后,就处于就绪状态,等到JVM里的线程调度器的调度;
  • 运行 :就绪状态下的线程在获取CPU资源后就可以执行run(),此时的线程便处于运行状态,运行状态的线程可变为就绪、阻塞及死亡三种状态。
  • 等待/阻塞/睡眠 :在一个线程执行了sleep(睡眠)、suspend(挂起)等方法后会失去所占有的资源,从而进入阻塞状态,在睡眠结束后可重新进入就绪状态。
  • 终止 :run()方法完成后或发生其他终止条件时就会切换到终止状态。
    在这里插入图片描述

1.3 线程的状态

  • NEW:还没开始运行的线程处于这种状态
  • RUNNABLE:在 Java 虚拟机中可运行的线程(正在运行也可能没在运行)处于这种状态
  • BLOCKED:被阻塞而等待监视锁的线程处于这种状态
  • WAITING:无限期的等待另一个线程执行特定方法的线程处于这种状态
  • TIMED_WAITING:在指定等待时间内等待另一个线程执行特定的方法的线程处于这种状态
  • TERMINATED:已经退出(运行结束)的线程处于这种状态
    在这里插入图片描述

1.3 创建线程的方式

1.3.1 继承 Thread 类

继承 Thread 类,覆写父类中的 run() 方法,新线程类创建线程

public class Thread1 extends Thread{
    public static void main(String[] args) {
        Thread1 thread1 = new Thread1();
        thread1.start();

        for (int i = 0; i < 200  ; i++) {
            System.out.println("------"+i);
        }
    }
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程"+i);
        }
    }
}

运行结果:
在这里插入图片描述

1.3.2 实现 Runnable 接口

实现 Runnable 接口,实现接口中的 run() 方法,Thread 类创建线程

public class Thread2 implements Runnable{
    public static void main(String[] args) {
        Thread2 thread2 = new Thread2();
        new Thread(thread2).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main线程"+i);
        }

    }
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("Runnable线程"+i);
        }
    }
}

运行结果
在这里插入图片描述

1.3.3 实现 Callable 接口

实现 Callable 接口,FutureTask 类构造创建方法体,Thread 类创建线程

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class CallableTest implements Callable<Integer> {
    public static void main(String[] args) {
        CallableTest callableTest = new CallableTest();
        FutureTask<Integer> ft = new FutureTask<Integer>(callableTest);
        Thread thread = new Thread(ft, "Callable线程");
        thread.start();
        try {
            System.out.println("callable线程返回值"+ft.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
    @Override
    public Integer call() throws Exception {
        int i=0;
        for(;i<100;i++){
            System.out.println(Thread.currentThread().getName()+"   "+i);
        }

        return i;
    }
}

在这里插入图片描述

1.3.4 三种不同方式对比

在这里插入图片描述

1.4 线程状态管理

- start():
在使用 new 关键字创建一个线程后(New 状态),并不表现出任何的线程活动状态(非 New、Terminated 状态,可以使用 isAlive 方法检测线程的活动状态),CPU 也不会执行线程中的代码。
只有在 start() 方法执行后,才表示这个线程可运行了(Runnable 状态),至于何时真正运行还要看线程调度器的调度。
在线程死亡后,不要再次调用 start() 方法。只能对新建状态的线程调用且只能调用一次 start() 方法,否则将抛出 IllegalThreadStateException 异常。
- run():
启动线程是 start() 方法,而不是 run() 方法。
如果直接调用 run() 方法,这个线程中的代码会被立即执行,多个线程就无法并发执行了。
- join():
等待该线程完成的方法,其他线程将进入等待状态(Waiting 状态),通常由使用线程的程序(线程)调用,如将一个大问题分割为许多小问题,要等待所有的小问题处理后,再进行下一步操作。
- sleep():
主动放弃占用的处理器资源,该线程进入阻塞状态(Blocked 状态),指定的睡眠时间超时后,线程进入就绪状态(Runnable),等待线程调度器的调用。
- yield():
主动放弃占用的处理器资源,线程直接进入就绪状态(Runnable),等待线程调度器的调用。
可能的情况是当线程使用 yield 方法放弃执行后,线程调度器又将该线程调度执行。
- interrupt():
没有任何强制线程终止的方法,这个方法只是请求线程终止,而实际上线程并不一定会终止,在调用 sleep() 方法时可能会出现 InterruptedException 异常,你可能会想在异常捕获后(try-catch语句中的catch)请求线程终止,而更好的选择是不处理这个异常,抛给调用者处理,所以这个方法并没有实际的用途,还有 isInterrupted() 方法检查线程是否被中断。
- setDaemon():
设置守护进程,该方法必须在 start() 方法之前调用,判断一个线程是不是守护线程,可以使用 isDaemon() 方法判断。
- setPriority():
设置线程的优先级,理论上来说,线程优先级高的线程更容易被执行,但也要结合具体的系统。
每个线程默认的优先级和父线程(如 main 线程、普通优先级)的优先级相同,线程优先级区间为 1~10,三个静态变量:MIN_PRIORITY = 1、NORM_PRIORITY = 5、MAX_PRIORITY = 10。
使用 getPriority() 方法可以查看线程的优先级。
- isAlive():
检查线程是否处于活动状态,如果线程处于就绪、运行、阻塞状态,方法返回 true,如果线程处于新建和死亡状态,方法返回 false。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值