多线程

java多线程

相关概念讲解

进程

  • 是指一个内存中运行的应用程序,每个进程都有独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位,系统运行一个程序即是一个进程从创建,运行到消亡的过程。

线程

  • 进程内部的一个独立执行单元;一个进程可以同时并发的运行多个线程,可以理解为进程便相当于一个单CPU操作系统,而线程便是这个系统中运行的多个任务。

  • windows系统中任务管理器,下图

在这里插入图片描述

  • 简单说如果进程是火车的话,那么线程就是火车的每一节车厢
  • 多线程优点
    • 不会阻塞用户,因为线程是独立的,可以同时执行多个操作。
    • 可以一起执行许多操作,节省时间。
    • 线程是独立的,因此如果在单个线程中发生异常,他不会影响其他线程。

并行

  • 指两个或两个以上事件在同一时刻发生。
  • 简单说就是你在吃饭的时候,电话响了,你一边打电话,一边吃饭

并发

  • 指两个或多个事件在同一时间段内发生。
  • 简单说就是你在吃饭的时候,电话响了,然后你去接电话,电话打完又接着吃饭

在这里插入图片描述

多任务处理

  • 多任务处理是同时执行多个任务的过程,使用多任务来利用CPU,多任务处理可以通过两种方式实现:
    1. 基于进程的多任务处理(多进程)
    2. 基于线程的多任务处理(多线程)
  • 基于进程的多任务处理
    • 每个进程在内存中都有一个地址,也就是说,每个进程分配一个单独的内存区域。
    • 进程是重量级的。
    • 进程之间通信的成本很高。
    • 从一个进程切换到另一个进程需要一些时间来保存和加载寄存器,内存映射,更新列表等。
  • 基于线程的多任务处理
    • 线程共享相同的地址空间。
    • 线程是轻量级的。
    • 线程之间通信成本很低。
    • 一次只能执行一个线程。

线程的生命周期(线程状态)

  • 线程的生命周期,线程的生命周期由JVM控制。
    1. **初始(New):新创建一个线程对象,但还没有调用start()**方法。
    2. 运行(Runnable):java线程中将就绪(ready)运行中(running)两种状态统称为“运行”。线程对象创建后,其他线程(如main线程)调用该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间后变为运行中状态(running)
    3. **阻塞(Blocked)?*表示线程阻塞于锁。
    4. **等待(Waiting)?*进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
    5. 超时等待(Timed_Waiting):该状态不同于Waiting,它可以在指定的时间后自行返回。
    6. **终止(Terminated)?*表示该线程已经执行完毕。

在这里插入图片描述

线程状态

  1. 新建(new):如果创建Thread类的实例但在调用**start()**方法前,线程处于新建(new)状态。
  2. 就绪(Runnable):调用start()方法后,线程处于runnable状态,但线程调度程序尚未选择它作为正在运行的线程。
  3. **运行(Running):**如果线程调度程序已选择它,则线程处于运行状态.
  4. **阻塞(Blocked)?*这时线程仍处于活动状态但当前没有资格运行的状态。
  5. **终止(Terminated):run()**方法退出时,线程处于终止或死亡状态。

线程创建方式

  • 创建线程的方式有
    • 通过继承Thread
    • 通过实现Runnable接口

Thread类简单介绍

  • Thread类提供了在线程上创建和执行操作的构造函数和方法,Thread类扩展了Object类并实现了Runnable接口。

在这里插入图片描述

常用的Thread类构造函数

  • Thread()
  • Thread(String name)
  • Thread(Runnable r)
  • Thread(Runnable r,String name)

常用方法

方法名概述
public void run()用于执行线程的操作
public void start()开始执行线程,JVM调用线程上的run()方法
public void sleep(long miliseconds)按指定的毫秒数等待线程死亡
public void join()等待线程死亡
public void join(long miliseconds)按指定的毫秒数等待线程死亡
public void getPriority()返回线程的优先级
public void setPriority(int priority)更改线程的优先级
public void stop()用于停止线程(deprivated)

代码演示

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

    public static void main(String[] args) {
        Thread1 th = new Thread1();
        Thread t = new Thread();
        t.start();
    }
}
  • 控制台输出

在这里插入图片描述

  • join方法简单演示
/**
 * @program: Bridge Pattern
 * @description:join()无参方法测试
 * @author: Mr.Yan
 * @create: 2019-03-21 20:53
 **/

public class JoinDemo1 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print(i + " ");
        }
    }

    public static void main(String[] args) {
        JoinDemo1 dj1 = new JoinDemo1();
        JoinDemo1 dj2 = new JoinDemo1();
        JoinDemo1 dj3 = new JoinDemo1();
        dj1.start();
        try {
            dj1.join();
        }catch (Exception e) {
            System.out.println(e);
        }
        dj2.start();
        dj3.start();
    }

}

  • 控制台输出
0 1 2 3 4 5 6 7 8 9 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 
  • 我们可以看到当dj1执行完毕之后,dj2和dj3才开始执行
  • join(long miliseconds)方法简单演示
public class JoinDemo2 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        JoinDemo2 jd1 = new JoinDemo2();
        JoinDemo2 jd2 = new JoinDemo2();
        JoinDemo2 jd3 = new JoinDemo2();
        jd1.start();
        try {
            jd1.join(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        jd2.start();
        jd3.start();
    }
}

  • 查看控制台发现,当jd1完成其任务2000毫秒后,jd2和jd3才开始执行

Runnable接口简单介绍

  • Runnable接口由任何其实例由线程执行类实现,Runnable接口只有一个**run()**方法。

  • public void run(); //用于执行线程的操作
    

代码演示

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

    public static void main(String[] args) {
        Thread1 th = new Thread1();
        Thread t = new Thread(th);
        t.start();
    }
}
  • 控制台输出

在这里插入图片描述

Thread 与 Runnable区别

  • 使用继承的话,不适合资源共享,实现接口,容易实现资源共享。
  • java是单继承,多实现的。

Thread类中的start() 与 run() 方法的区别

  • **start()**方法用来启动新创建的线程。
  • **run()**方法只会在原来线程中调用,没有新线程的启动。

本案例代码均已放置到github,点击获取
个人博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值