Java 多线程 万字最详解

Java多线程

多线程概述

线程与进程

进程

  • 是内存中运行的应用程序,每个进程都有一个独立的内存空间

线程

  • 值进程的执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程最少有一个线程
  • 线程实际上是在进程基础上的进一步划分,一个进程启动之后,里面若干的执行路径又可以划分成若干个线程

线程调度

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eoKunGnP-1620203162745)(/Users/faro_z/Library/Application Support/typora-user-images/image-20210504211610442.png)]

分时调度

  • 所有线程,轮流使用 CPU,平均分配每个线程占用 CPU 的时间

抢占式调度

  • 当 CPU 空闲的时候,CPU 会抛出一个时间片,谁抢到就是谁的。优先让优先级高的线程使用 CPU;如果线程优先级相同,那么,会随机选择一个(线程随机性),Java 使用的就是抢占式调度
  • CPU 使用抢占式调度模式在多个线程之间高速切换,对于 CPU 而言,某时刻,只能执行一个线程,而 CPU 在多个线程切换的速度很快,在我们看来,就像是多个线程在同时执行一样。其实多线程程序并不能提高程序的运行速度(甚至会因为切换的时候的时间消耗,使得总耗时还边长),但是能提高程序的运行效率,让 CPU 使用率更高。

同步与异步

**同步:**排队执行,效率低但是安全

**异步:**同时执行,效率高但是数据不安全

并发与并行

并发:指两个或多个事件,在==同一时间==内发生。(比如说一天内,一小时内)

**并行:**指两个或多个事件,在同一时间发生(同时发生)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UZDhhlwB-1620203162747)(/Users/faro_z/Library/Application Support/typora-user-images/image-20210504212449234.png)]

线程阻塞

一般,比较耗时的操作,可以看成是线程阻塞

比如说,我们要等待用户输入,那么,那一段线程,就是阻塞了

Java 多线程的实现

java 中实现多线程,一共有三种方法

  • 继承 Thread 类
  • 实现 Runnable 接口
  • 实现Callable 接口

继承 Thread 类

public class ThreadDemo {
   
    public static void main(String[] args) {
   
        new ThreadClass().start();
        for (int i = 0; i < 10; i++) {
   
            System.out.println("锄禾日当午"+i);
        }
    }
}

class ThreadClass extends Thread {
   

    @Override
    public void run() {
   
        for (int i = 0; i < 10; i++) {
   
            System.out.println("汗滴禾下土"+i);
        }
    }
}

image-20210504213505849

image-20210504213140920

每个线程都有自己的栈空间,但是共用一个堆空间

实现 Runnable 接口

public class RunnableDemo {
   
    public static void main(String[] args) {
   

        //子线程
        new Thread(() -> {
   
            for (int i = 0; i < 10; i++) {
   
                System.out.println("汗滴禾下土"+i);
            }
        }, "子线程").start();

        //主线程(的一部分,整个 main 都是主线程)
        for (int i = 0; i < 10; i++) {
   
            System.out.println("锄禾日当午"+i);
        }
    }
}

实现 Callable<T>接口

Callable,是带返回值的线程

上面两个实现方法,可以看成主线程之外的子线程去完成任务,和主线程无关了

但是 Callable,相等于主线程让子线程去完成任务,等到子线程任务完成了,再给主线程返回一个结果。比如说,主线程可以派发 1000 个任务,给 1000 个线程,等着 1000 个任务执行完毕了,可以获得 1000 个结果。

Callable 的使用步骤如下:

  1. 编写实现 Callable 接口,实现 call 方法
class Xxx implements Callable<T> {
   
		@Override
		public <T> call() throws Exception {
   
			return T;
		}
	}
  1. 创建 FutureTask 对象,并传入编写的 Callable 对象
FutureTask<Integer> task = new FutureTask<>(callable);
  1. 通过 Thread,启动线程
new Thread(task).start

获取子线程返回结果的方法如下:

  • 使用 FutureTask 的get()方法

**注意:**使用get()会让主线程等待子线程执行完毕,然后去获得方法

public class CallableDemo {
   
    public static void main(String[] args) throws InterruptedException, ExecutionException {
   
        MyCallable cl = new MyCallable();
        FutureTask<Integer> task = new FutureTask<>(cl);
        //执行子线程
        new Thread(task).start();
        Integer res = task.get();
        System.out.println("子线程计算结果为:"+res);
        for (int i = 0; i < 10; i++) {
   
            Thread.sleep(100);
            System.out.println("main"+i);
        }

    }
}

class MyCallable implements Callable<Integer> {
   

    @Override
    public Integer call() throws Exception {
   
        for (int i = 0; i < 10; i++) {
   
            Thread.sleep(1000);
            System.out.println("子线程正在执行"+i);
        }
        return 100;
    }
}

image-20210505155751891

  • 使用使用 FutureTask 的isDone()方法

可以先判断子线程有没有执行完,执行完了,再去获取子线程的返回值,避免主线程等待

public class CallableDemo2 {
   
    public static void main(String[] args) throws InterruptedException, ExecutionException {
   
        MyCallable2 cl = new MyCallable2();
        FutureTask<Integer> task = new FutureTask<>(cl);
        new Thread(task).start();
        for (int i = 0; i < 10; i++) {
   
            Thread.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FARO_Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值