java中多线程、并发、并行、线程与进程、线程调度、创建线程的方式

多线程

多线程比单线程快,前面简单介绍过:集合如果是不安全的,那么它就是多线程的,了解多线程之前,先了解什么是并发和并行。

并发:指两个或多个事件在同一个时间段内发生。

并行:指两个或多个事件在同一时刻发生,这里强调同一时刻,并行的速度快于并发。
请添加图片描述
线程与进程:

进程:指一个内存中运行的应用程序,每个进程都有一个独立的空间,一个应用程序可以同时运行多个进程,进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个程序从创建到运行再到消亡的过程。
请添加图片描述
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程,一个进程中是可以有多个线程的,这个应用程序可以称为多线程程序。简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程。

CPU:计算机中央处理器,可以对数据进行计算,指挥计算机中软件和硬件工作。
请添加图片描述
线程调度

分时调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间。

抢占调度:优选让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个线程执行,java使用的是抢占式调度。
请添加图片描述
创建线程类:

主线程:执行主方法(main)的线程被称作主线程。

单线程实现一个业务:

// 主线程:执行主方法(mian)的线程
// java默认是单线程的,从mian方法中开始,从上到下依次执行。
public class MainClass {
    
    
    public static void main(String[] args) {
    
    
        // 创建第一个对象:
        Person p1 = new Person("小明");
        p1.consoleHandle();

        // 创建第二个对象:
        Person p2 = new Person("小红");
        p2.consoleHandle();

        // 执行此程序,可以看到到上面部分从上到下依次执行:
        // 小明--0
        // 小明--1
        // 小红--0
        // 小红--1
        
        System.out.println(1 / 0); // 执行完上面的代码后,从这里开始报错Exception in thread "main"单线程程序中,抛出异常后,后面的代码将不能在执行,多线程的话可以将多个业务放到不同的线程中去,这样即使一个线程中抛出了异常,另一个线程也不会被影响到。
        System.out.println(5);
    }
}

创建一个多线程程序

在lang包下有一个Thread类,代表线程,用来描述多个线程。java中创建线程有两种方式。

方式一:将类声明为Thread的子类,该子类应该重写Thread的run方法,,如:

定义一个多线程的类:

// 创建线程的第一种方式:创建Thread子类:
// 想要实现多线程,就要继承Thread类,其步骤:1.创建一个Thread子类、2.在该子类中重写run方法,设置线程任务(该线程要做什么)3.创建该类的实例对象 4.调用该实例的start方法开启新的线程(调用start方法会开辟新的线程,虚拟调用该线程的run方法)
// run执行的结果是两个线程并发的运行,当前线程(main线程,从调用返回给start方法)和另一个线程(创建的新线程,执行其run方法)
// start方法,一个线程只能调用一次,多次启动一个线程是非法的,特别是当线程已经结束执行后,不能再重新启动。

// 1.创建一个Thread的子类:
public class OneThreadClass extends Thread {
    
    
    // 2.重写run方法
    @Override
    public void run () {
    
    
        // run方法里面用来设置任务,这里还是以循环为例:
        for (int i = 0; i < 2; i++) {
    
    
            System.out.println("run1--" + i);
        }
    };
}

实例化一个多线的类:

public class TestOneThreadClass {
    
    
    public static void main(String[] args) {
    
    
        // 3.创建一个多线程类的实例:
        OneThreadClass ot = new OneThreadClass();
        // 4.调用该实例的start方法(start方法继承于Thread类)让其调用run方法来执行任务:
        ot.start();

        // 主线程也执行for
        for (int i = 0; i < 2; i++) {
    
    
            System.out.println("main--" + i);
        }

        // 打印到控制台的结果如下:可以看到此时程序不是从上到下依次执行了,原因是这里是个多线程的,多个线程抢占cpu执行,同一优先级随机选择一个线程执行
        // main--0
        // run1--0
        // main--1
        // run1--1
    }
}

程序执行图:
请添加图片描述
内存图:
请添加图片描述
Thread类的常用方法

创建一个继承Thread的类:

public class MyThread extends Thread {
    
    
    public MyThread() {
    
    
    }

    // 4.修改线程名称还有一种方式就是通过构造方法调用super将名称传给super,注意重载格式是(String name)这个,如:
    public MyThread(String name) {
    
    
        super(name);
    }

    @Override
    public void run () {
    
    
        // 1.Thread类的getName可以获取到线程的名称:
        String nm = getName();
        System.out.println(nm); // Thread-0, 每创建一个线程,并执行start方法后,会新增一个后面索引增加1的新线程

        // 2.Thread类的currentThread返回当前正在执行的线程对象的索引:
        System.out.println(Thread.currentThread()); // Thread[Thread-1,5,main] 和 Thread[Thread-0,5,main] Thread[线程001,5,main] Thread[线程003,5,main]
        System.out.println(Thread.currentThread().getName()); // Thread-0 和 Thread-1 线程001 线程003
    };
}

使用继承了Thread类的类:

public class UseMyThread {
    
    
    public static void main(String[] args) {
    
    
        MyThread mt = new MyThread();
        mt.start();

        new MyThread().start();

        // 3.Thread类的setName(String name)设置线程的名字:
        MyThread mt2 = new MyThread();
        mt2.setName("线程001");
        mt2.start();

        // 4-2:对构造方法直接修改名称的测试:
        MyThread mt3= new MyThread("线程003");
        mt3.start();

        // 5.Thread的sleep(mills)方法,让线程休眠n毫秒后继续执行,如:正常一个循环会很快的执行完,此时用sleep给它休眠5000毫秒执行,就可以看到每各5秒钟打印一次:
        for (int i = 0; i < 10; i++) {
    
    
            System.out.println(i);
            try {
    
    
                // 本身会报异常,使用try/catch处理下即可
                Thread.sleep(5000);
            } catch (InterruptedException e) {
    
    
                throw new RuntimeException(e);
            }
        }
    }
}

创建多线程的第二种方式(推荐方式):

继承Runnable接口实现类:

// 1.创建一个Runnable接口的实现类
public class RunnableTmplClass implements Runnable {
    
    
    // 2.在实现类中重写Runnbale接口的run方法,设置线程任务
    @Override
    public void run() {
    
    
        for (int i = 0; i < 5; i++) {
    
    
            System.out.println(Thread.currentThread().getName() + "--" + i);
        }
    }
}

测试第二种方式实现多线程:

// 创建多线程的第二种方式:实现Runnable接口:
// Runnable接口应该由那些打算通过某一线程执行某实例的类来实现,类必须定义一个称为run的无参数方法。
// 实现步骤: 1.创建一个Runnable接口的实现类 2.在实现类中重写Runnbale接口的run方法,设置线程任务 3.创建一个Runnable接口的实现类对象 4.创建Thread类对象,构造方法中传递Runnable接口实现类对象 5.调用Thread类中的start方法,开启新的线程执行run方法
public class TwoThreadClass {
    
    
    public static void main(String[] args) {
    
    
        // 3.创建一个Runnable接口的实现类对象
        RunnableTmplClass rt = new RunnableTmplClass();
        // 4.创建Thread类对象,构造方法中传递Runnable接口实现类对象
        Thread td = new Thread(rt);
        // 5.调用Thread类中的start方法,开启新的线程执行run方法
        td.start();
        for (int i = 0; i < 5; i++) {
    
    
            System.out.println(Thread.currentThread().getName() + "--" + i);
        }
    }
}

前两种创建线程方式之间的区别:

1.实现Runnable接口创建多线程:

避免了单继承的局限性(一个类只能继承一个父类,如果类继承了Thread类后就无法再继承其他类了),但是实现了Runnable接口后还可以继承其他类,实现其他的接口。

2.增强了程序的扩展性,降低了程序的耦合性(解耦,实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离,可以实现多个Runnable接口实现类并设置run方法任务,给Thread类创建对象使用)。

匿名内部类方法实现线程的创建

// 匿名内部类方式实现线程的创建
// 匿名内部类的作用:简化代码,把子类继承父类,重写父类的方法,创建子类对象合在一起完成,把实现类实现接口,重写接口中的方法,创建实现类对象合成一步完成
// 匿名内部类的最终产物:子类、实现类对象,这个类没有名字
// 格式:new 父类/接口(){重复父类/接口中的方法}
public class ThreeThreadClass {
    
    
    public static void main(String[] args) {
    
    
       // 线程的父类是Thread
        new Thread(){
    
    
            @Override
            public void run(){
    
    
                for (int i = 0; i < 5; i++) {
    
    
                    System.out.println(Thread.currentThread().getName() + "----" + i);
                }
            };
        }.start();
    }
}

提示:本文图片等素材来源于网络,若有侵权,请发邮件至邮箱:[email protected]联系笔者删除。
笔者:苦海

猜你喜欢

转载自blog.csdn.net/weixin_46758988/article/details/128357638