多线程的原理、实践、应用

1  多线程的介绍

1.1  操作系统的演进过程

批处理操作系统(单道和多道):

计算机能够自动地、成批地处理一个或多个用户的作业。不过单道批处理系统在进行I/O操作的时候,CPU资源是没有被利用的,为了能够更高效的利用cpu资源,多道批处理系统诞生了。

单道批处理操作系统工作图示:




 多道(两道)批处理操作系统工作图示:

分时操作系统

批处理系统对于用户需要的计算机系统来说缺少交互性,工作之间的独立性。以及能在预期时间内完成用户需要的任务。分时操作系统产生了,它支持多用户交互式操作系统,每个用户可以通过自己的终端向系统发出各种操作控制命令,完成作业的运行。分时是指把cpu的运行时间分成很短的时间片,按时间片轮流把cpu资源分配给各任务使用。

分时操作系统工作图示:

实时系统:常用于飞机飞行、导弹发射,等场景,这里不做详细介绍。

1.2 线程和进程的关系

介绍完操作系统之后再来看进程和线程。随着计算机硬件的发展,计算机的内存越来越大,cpu数也越来越多。进程和线程为了更好的利用计算机资源自然而然的诞生了。
进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,系统会给每个进程分配独立的内存地址空间,并且每个进程的地址不会相互干扰。对于单核CPU来说,在任意一个时刻,只会有一个任务去执行,只是通过切换时间片的方式完成了并行执行。多个进程之间通过CPU时间片的不断切换交替执行(给人的感觉就是应用程序同时进行的,所以你可以无感知的一边写代码,一边听歌)。
线程
线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,每个线程会负责一个独立的子任务,进程在一个时间内只能干一件事情,如果想同时干多件事情的话, 就要把进程中的多个子任务划分到多个线程,利用线程更高效的完成任务。

2  多线程的适合场景

什么情况下需要使用多线程呢?对于我们编写程序来说一般一个主线程就可以处理所有的事情,但是当我们需要对于一些耗时操作做一些优化的时候,可以考虑多线程。

  • 需要多次从其他rpc服务取数据,可以考虑利用多线程获取数据,都返回之后再统一处理。
  • 需要从数据库中的多个表中取数据,可以考虑利用多线程从表取数据,然后再处理。
  • 需要我们需要导入一个较大的表格数据的时候,可以考虑利用多线程分批导入数据等等。

使用多线程时需要我们注意⚠️ 因为多线程之间执行是无序的,我们需要确定并行的任务之间是独立的才可以。如果两个线程之间的任务不是独立的,需要利用线程安全的变量做线程之前的通信。

3  多线程的实践(java)

3.1 我们先来看一下如何创建一个线程

通过继承Thread类

public class TestThread extends Thread {

    public TestThread() {
    }

    @Override
    public void run() {
        System.out.print("当前执行线程是:" + this.getName() + "  ");
    }

    public static void main(String[] args) {

        System.out.println("当前的线程是" + Thread.currentThread().getName());
        TestThread testThread1 = new TestThread();
        TestThread testThread2 = new TestThread();
        testThread1.start();
        testThread2.start();
    }
}

实现Runnable接口

public class TestRunnable implements Runnable {
    private int count = 10;

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "运行  count= " + count--);
        }
    }

    public static void main(String[] args) {
        TestRunnable testRunnable = new TestRunnable();
        new Thread(testRunnable, "C").start();
        new Thread(testRunnable, "D").start();

    }
}

实现Callable接口


import java.util.concurrent.*;

public class TestCallable implements Callable<Integer> {

    private final static ExecutorService executor = Executors.newCachedThreadPool();

    private Integer number;

    public TestCallable(Integer number) {
        this.number = number;
    }

    @Override
    public Integer call() throws Exception {
        System.out.println("线程number=" + number);
        return number;
    }

    public static void main(String[] args) {
        executor.submit(new TestCallable(1));
    }
}

从JDK 1.5之后,提供了Calla

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值