Java之多线程初阶

目录

一.进程和线程

1.什么是进程

2.并发,并行和串行

3.线程和多线程

4.进程和线程的区别(重点)

5.多线程的优点

6.多线程的缺点

二.线程的创建

1.继承Thread类

2.实现Runnable接口重写run()方法

3.通过匿名内部类的方式创建Thread和实现Runnable

4.通过Lambda表达式来实现一个线程

三.查看Java中创建线程的状态

1.直接到JDK中寻找jconsole.exe文件

 2.命令行中直接搜索jconsole


一.进程和线程

1.什么是进程

在计算机中,进程是指正在运行的程序的实例。进程是操作系统进行资源分配和调度的基本单位。

每个进程都有其独立的内存空间和数据栈,使得它们之间相互隔离,避免了不同进程之间的数据干扰。操作系统通过分配资源,管理进程间的调度,使得进程可以有序、并发地运行。同时,进程之间也可以通过各种通信机制进行数据传输和共享,这些通信机制可以使不同进程之间协同工作,共同完成任务。

进程可以处于不同的状态,例如运行、就绪、堵塞等,进程状态的变化可以由内部事件和外部事件引起。内部事件包括程序的运行、资源的申请和释放等,而外部事件则包括输入/输出请求、信号等。操作系统会根据不同的事件,将进程切换到不同的状态,以便对进程进行管理和调度。

2.并发,并行和串行

串行(Serial)指的是一个任务或进程按顺序逐个完成,一个任务完成后,另一个任务才开始执行。例如,一个计算机需要处理多个任务,这个时候串行是一个任务执行完毕之后,才能处理下一个任务.

并发(Concurrent)指的是多个任务在相同时间段内交替执行。在单处理器系统中,实现并发需要快速地在多个任务之间切换。例如,一个计算机需要同时运行多个应用程序,每个应用程序都有一个单独的进程,操作系统需要在这些进程之间快速地切换。

并行(Parallel)指的是多个任务同时执行,每个任务在不同的处理器独立运行。并行需要多个处理器或多个计算机来同时执行不同的任务。例如,一个大型计算任务被分成多个子任务,每个子任务分配到不同的处理器或计算机上执行。

在计算机领域中,并行和并发的概念通常被用来提高系统性能和响应能力。通过同时执行多个任务或进程,可以最大限度地利用计算机系统的资源。而串行则在某些情况下更为简单和可控,例如在单线程程序或少量任务的情况下。

再来举一个生活中的例子,当我们在吃饭(任务A)的时候,这个时候电话铃响了.

①串行:我们需要吃完饭之后,才能进行接电话(任务B).

②并发:我们一会去接电话,一会吃饭,同时只进行一个任务,但是可以快速的切换这两个任务,一会进行任务A,一会进行任务B.

③并行:我们一边吃饭,一边接电话,任务A和任务B同时进行

3.线程和多线程

多线程是指在一个进程中同时运行多个线程的技术。线程是指一个程序内部的执行路径,每个线程都拥有自己的堆栈和寄存器,并且能够访问共享内存中的变量和对象。与进程相比,线程是轻量级的,一个进程可以同时拥有多个线程

为什么要存在线程呢?

根据上面定义我们可以知道线程是轻量级的.多线程的开辟比多进程的开辟更能解决资源的消耗问题.下面是进程开辟时需要进行的操作:

这样显然是十分消耗内存的,因此便有了线程

创建线程只关注要处理的任务,使用的是进程创建时申请到的所有资源

案例:创建工厂

张三需要创建工厂生产生活用品,他需要在厂区申请一块地皮创建工厂(CPU给进程分配资源),工厂就相当于一个线程,这个厂区还有其他的工厂,别人的工厂(其他的线程),他们之前生产的东西之间互不影响.然后张三的工厂里面有需要的生产线(线程),负责生产不同的产品(也可能不同的生产线生产相同的产品),各个生产线之间可以相互影响(线程可以相互影响).申请地皮创建工厂的花费是很大的,需要建设厂房,购买基础设施等等(进程的创建的代价很大),而一条生产线可以相对容易的创建(线程的创建较容易).因此张三需要夸大生产,可以优先考虑创建生产线(进程)

4.进程和线程的区别(重点)

  1. 对于进程而言,至少有一条线程(主线程).
  2. 进程是申请系统资源的最小单位.
  3. 线程是CPU调度的最小单位.
  4. 进程之间互不影响,线程之间可以互相影响.

5.多线程的优点

  1. 充分利用CPU的资源
  2. 利用轻量级线程的特性减少系统的开销  

    a.线程创建的效率比进程高                                                                                                     b.线程销毁的效率比进程高                                                                                                     c.线程调度的效率比进程高

6.多线程的缺点

多线程也可以存在一些问题

这里我们拿小呆呆吃100个棒棒糖为例

如何我们使用多进程的话,需要的是两个桌子,每个桌子各放50个棒棒糖,然后进行吃

 

如果采用多线程的模式化,只需要在一个桌子上多增加几个小呆呆进行吃

 

但是可能会发生这样一个问题,当我们不断的增加小呆呆的数量,小呆呆达到一定的数量之后,这样不但没有提高效率,反而会给CPU增加负担.因此在真实的程序中,确定线程的数量,需要反复的测试.

 还有可能出现以下问题

当还有一个棒棒糖的时候.,但这是有两个小呆呆,这个时候两个小呆呆争抢一个棒棒糖,会出现线程不安全的问题.

二.线程的创建

Java中的JDK给我们提供了API来创建线程(Thread类)

1.继承Thread类

public class Demo2_Thread {
    public static void main(String[] args) {
        MyThread02 thread02 = new MyThread02();
        thread02.start();
        while (true){
            System.out.println("main thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}
class MyThread02 extends Thread{
    @Override
    public void run() {
        while (true){
            System.out.println("my thread ");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

run()方法中表示的就是这个线程中需要执行的任务

注意: 我们自定义的继承的Thread的类重写的是run()方法,而我们启动的线程的时候调用的是start()方法,如果我们调用成了run()方法,就仅仅是类中一个方法的调用,而start()方法才是创建一个线程,具体我们可以看一下源码start()方法.

 代码的运行结果

 从代码的运行结果我们可以总结出两个线程(主线程main和my thread)并不是有序执行的,因为CPU的调度是随机的.   线程的执行是抢占式执行

2.实现Runnable接口重写run()方法

public class Demo3_Runnable {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        //创建线程
        Thread thread = new Thread(myRunnable);
        thread.start();
        while (true) {
            System.out.println("main thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}

class MyRunnable implements Runnable {
    //需要执行的任务
    @Override
    public void run() {
        while (true) {
            System.out.println("生产皮包,金币+1");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {

            }
        }

    }
}

使用Runnable定义任务的好处:

1.解耦,把定义线程和定义任务分开 

2.将定义线程和定义任务分开 ,以便修改代码时可以统一的进行修改

解耦:把不同的功能分开,如何要修改或查找指定的功能的代码可以到指定位置进行操作.

3.通过匿名内部类的方式创建Thread和实现Runnable

public class Demo4_Annoation {
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("hello Thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        thread.start();
        while (true){
            System.out.println("main thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

4.通过Lambda表达式来实现一个线程

对Lambda表达式不熟悉的可以看这一篇博客:Java8新特性之Lambda表达式和Stream API

public class Demo5_Lambda {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println("hello Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();
        while (true){
            System.out.println("main thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

 其实这个就是类似于实现Runnable,因为Runnable接口是一个函数式的接口,而且其中的方法run()没有参数,所以可以直接用上面的格式进行实现, 大括号里面就是线程需要执行的功能

三.查看Java中创建线程的状态

1.直接到JDK中寻找jconsole.exe文件

双击打开,找到自己运行的线程进行查看

点击不安全连接进行查看

 点击上方的线程,查看自己的线程信息,默认的线程Thread0开始,也可以在代码中给自己的线程进行命名操作

A3MUCFZVIdtQAAAAAElFTkSuQmCCwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 2.命令行中直接搜索jconsole

猜你喜欢

转载自blog.csdn.net/qq_64580912/article/details/130497463