Java 之 多线程

100 阅读1分钟

「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战

并发和并行

并行:在同一时刻,有多个指令在多个CPU上同时执行。

并发:在同一时刻,有多个指令在一个CPU上交替执行。

进程和线程:

进程:是正在运行的软件

独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位。

动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的。

并发性:任何进程都可以同其他进程一起并发执行。

线程:是进程中的单个顺序控制流,是一条执行路径。

单线程:一个进程如果只有一条执行路径,则称为单线程程序。

多线程:一个进程如果有多条执行路径,则称为多线程程序。

多线程的实现方案:

  1. 继承Thread类的方式进行实现
  2. 实现Runnable接口的方式进行实现
  3. 利用Callable和Future接口方式实现

多线程的实现方案:

方案1:继承Thread 类

定义一个类MyThread继承Thread类。

在MyThread类中重写run() 方法

创建MyThread 类的对象

启动线程

public class MyThread extends Thread{
    @Override
    public void run() {
//        super.run();
        // 代码就是线程在开启之后执行的代码
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        
        // t1.run()// 表示的仅仅是创建对象,用对象去调用方法,并没有开启线程。
        t1.start();
        t2.start();


    }
}

两个小问题:

为什么要重写run() 方法?

因为run() 是用来封装被线程执行的代码

run() 方法和start() 方法的区别?

run(): 封装线程执行的代码,直接调用,相当于普通方法的调用,并没有开启线程。

start(): 启动线程,然后由JVM 调用此线程的run()方法。

方式2:实现Runnable接口

多线程的实现方式:

方式2:实现Runnable接口

1.定义一个类MyRunnable实现Runnable接口

  1. 在MyRunable类中重写run()方法

  2. 创建MyRunnable类的对象

  3. 创建Thread类的对象,把MyRunnable对象作为构造方法的参数

  4. 启动线程


public class MyRunnable implements Runnable{
    @Override
    public void run() {
        // 线程启动后执行的代码
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        // 创建了一个参数的对象
        MyRunnable mr = new MyRunnable();
        // 创建一个线程对象,并把参数传递给这个线程
        // 在线程启动之后,执行的就是参数里面的run方法
        Thread thread = new Thread(mr);
        // 开启线程
        thread.start();

        // 创建了一个参数的对象
        MyRunnable mr2 = new MyRunnable();
        // 创建一个线程对象,并把参数传递给这个线程
        // 在线程启动之后,执行的就是参数里面的run方法
        Thread thread2 = new Thread(mr2);
        // 开启线程
        thread2.start();
    }
}

方式3:Callable和Future

多线程的实现方式:

  1. 定义一个类MyCallable实现Callable接口

  2. 在MyCallable类中重写Call()方法

  3. 创建MyCallable类的对象

  4. 创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数

  5. 创建Thread类的对象,把FutureTask对象作为构造方法的参数

  6. 启动线程

public class Demo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 线程开启之后,需要执行里面的call方法
        MyCallable mc = new MyCallable();
        // 可以获取线程执行完毕之后的结果,也可以作为参数传递给Thread对象。
        FutureTask<String> ft = new FutureTask<>(mc);
        // 创建线程对象
        Thread t1 = new Thread(ft);
        // 开启线程
        t1.start();
        String s = ft.get();
        System.out.println(s);
    }
}

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {

        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
        // 返回值就表示线程运行完毕后的结果
        return "aaa";
    }
}