ok,那么接下来我们走进这个多线程之旅。

当然,我们得认识什么是线程。

那么,认识这个线程之前,我们得先认识下进程先。

那么什么又是进程呢?

进程:是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。

可以简单来说,进程就是电脑中正在运行的一个独立任务,它有自己需要的资源和执行步骤,可以和其他任务并行运行。

那么这个进程需要占用一定的系统资源,包括内存,CPU时间,文件句柄等,所以比较”重“

接着,我们就引入这个线程。

那什么又是线程呢

线程:

是进程中的一个实体,是CPU调度和分派的基本单位,它是比进程更小的独立运行单位。

这个线程比进程更为轻量,那么我们一般使用这个多线程编程,使我们电脑上的多核心都不闲着,充分利用这个多核心资源。

那么,刚刚可得一个重要的结论。

进程是系统资源分配的基本单位,线程是系统调度的基本单位。

在进程中,线程要么是包含一个,要么是多个,要么就是没有

线程在进程内部中,所以线程是共用进程的资源,即同一份系统资源。

刚刚说到,线程为什么比进程轻量呢?

这是因为线程与进程相比

创建线程,省去了”分配资源“、销毁线程,省去“释放资源",这些过程看着寥寥几个字

但是在系统中,可不是个容易的事,真要执行管理起来,开销是蛮大的。

那么什么又是多线程呢?

多线程:是一种通过并行处理来提升计算机程序运行效率的技术。

那么简单来说,就是干活的人多了

就像是进程得到一份任务了,然后多线程出来了,干活人变多起来,然后可以提高工作效率了。

当然,这里的提高工作效率可以说是,充分利用CPU多核心,”并行执行”任务。

那么要是我提高更多的线程,岂不是执行的更快?

理论上是的!

但是呢,由于我们的CPU核心数目有限,所以不能无休止的添加线程,

所以,一旦我们的线程超出了CPU核心数目,那么此时我们的线程会存在严重的竞争。

当然,解决办法也是简单粗暴的

就是添加更多核心数的CPU!

值得注意的是,如若一个线程执行读的任务操作,一个线程执行写的任务操作,对于同一份数据来说,那么此时就可能出现读的数据不一致的状况,这样的情况呢,就称为“线程安全”

这是多线程编程中非常值得注意的!

讲了,这么多,那么如何来用代码来实现这个多线程编程呢?

这里还要多说一点

这个线程是输入操作系统里的,那么我们操作的话,所以也是操作系统里的。

那么对于java来说呢,这些系统提高的线程API是被封装好了的,我们就可以愉快轻松的使用它啦。

当然,我们接触到的有Linux、windowes,那么对应的它们提高的系统API也是不一样的,甚至可以是说差异巨大呢!

那么进行多线程编程之前呢,那肯定是得创建这个线程先咯。

那么,这里介绍五种较为常见的创建线程的方法

创建线程

1.继承Thread类

class MyThread extends Thread{
    //继承Thread来实现线程创建@Overridepublic void run() {
        //Thread 中,这里是执行代码逻辑的while (true){
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
public class Demo {
    //main方法是一个主线程public static void main(String[] args) {
        MyThread myThread=new MyThread();
        //这里是开始创建一个线程,然后创建后,会默认调用run()方法//单纯使用run方法,不会创建新线程,//        myThread.run();
        myThread.start();
        //演示下并发执行过程while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

代码说明:

我们继承这个Thread类后,要去重写下这个run()方法

那么这个run方法是什么呢?

这个run()可以理解为一个让线程执行的一个个认为来的

里面的代码就是run()方法执行的任务内容

我这里的内容呢,是循环打印hello thread

然后呢,加上一个sleep()方法,给到1000ms,这是为什么呢?因为线程执行速度是蛮快的,所以

加上这个后,待会打印就可以看看其中的执行了,当然,这个sleep()有一个

异常:InterruptedException,所以我们用了try catch处理一下它。

在main方法中

我们实例化这个MyThread类的对象,然后让它去调用这个start()方法。

后面我们同样写了这个循环打印hello main的代码。

这是为什么呢?

这也是写这个也是为了方便我们感受下多线程执行的过程。

那么我们点击运行:

就会出现这样的打印。

注意!注意!

线程的调度是随机的,所以打印的顺序,不一定是从上到下的。

那么,有个疑问。这个hello thread不是run()方法执行的吗。但是main方法中,却没有调用就直接执行到了?

首先我们来理解下这个t.start()方法是干什么的

这个start()方法呢,简单来说呢它的作用就是创建一个线程。

此时,当一个线程创建后,就要执行任务了,那么run()方法里的内容是我们执行任务的代码。

所以,可以说是。run()方法是当线程被创建之后呢,就要执行它了。

所以当我们代码执行完t.start()方法后,run()方法就随之执行了!

2.实现Runnable接口

这个第二个方法就是去实现这个Runnable这个接口,然后去重写里面的run()方法

class MyThread2 implements Runnable{
    @Overridepublic void run() {
        while (true){
            System.out.println("hello world");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
public class Demo2 {
    public static void main(String[] args) throws InterruptedException {
        //通过实现Runnable来实现线程创建
        MyThread2 t=new MyThread2();
        Thread thread=new Thread(t);
        thread.start();
        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}这里的有些代码,是和代码一差不多的。

然后在main方法中

我们实例化我们的MyThread2对象

将对象的引用t作为参数给到Thread中,那么实例化出来的Thread再去调用start()方法,也可以执行代码了,

效果和方法一也是差不多的

3.通过Thread的匿名内部类来实现

public class Demo3 {
    //匿名内部类来实现public static void main(String[] args) throws InterruptedException {
        //通过Thread的匿名内部类来实现线程创建
        Thread t=new Thread(){
            @Overridepublic void run() {
                while (true){
                    System.out.println("hello world");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        t.start();
        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}

在这个匿名内部类中,又重写了run()方法,在这里面执行我们的逻辑。

然后用这个Thread类型的变量接受其返回值,再去调用这个start()方法。

效果和上面那两个差不多的

4.通过实现Runnable的匿名内部类

public static void main(String[] args) throws InterruptedException {
        //通过Runnable的匿名内部类来实现线程创建
        Runnable runnable=new Runnable() {
            @Overridepublic void run() {
                while (true){
                    System.out.println("hello world");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        Thread t=new Thread(runnable);
        t.start();
        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }

通过实现Runnable的匿名内部类后,我们接着实例化一个Thread对象,把runnable作为参数传给Thread

那么再通过t.start()方法来创建线程

最终效果其实和上述也是差不多的

那么方法四的代码也是可以这样写的,直接在new Thread()里面的参数传入new Runnable的匿名内部类

这样也是可以实现同样效果的

public static void main(String[] args) throws InterruptedException {
        //通过Thread的匿名内部类来实现线程创建
        Thread t=new Thread(){
            @Overridepublic void run() {
                while (true){
                    System.out.println("hello world");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        t.start();
        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }
}

5.通过lambda表达式来创建

  //lambda表达式创建线程public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(()->{
            while (true){
                System.out.println("hello world");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t.start();
        while (true){
            System.out.println("hello main");
            Thread.sleep(1000);
        }
    }

那么线程常见的创建方式,小编就分享到这里。

接下来总结下。

总结:

一:

1.进程是包含线程的

2.进程是系统资源分配的基本单位

线程是系统调度的基本单位

3.线程的不能无节制的创建,不能超过其CPU核心

4.线程的调度是随机,所以线程之间可能会相互影响,引入线程安全问题

5.进程之间不受影响,即一个进程崩溃了,不会影响到其他进程

二.

代码创建线程常用五种方式

1.通过继承Thread类实现

2.通过实现Runnable接口来实现

3.通过实现Thread的匿名内部类实现

4.通过实现Runnable匿名内部类实现

5.通过lambda表达式来实现。

文章作者: 南汐
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 www.phblog.cloud
JavaSE JavaSE
喜欢就支持一下吧