线程

1 线程概述

  • 线程的核心问题是线程提供了并行解决方案

2 线程的相关概念

2.1 进程

进程(Process)是计算机中的程序关于某数据集合上的一次运动活动,是操作系统进行资源分配与调度的基本单位。可以把进程简单的理解为正在操作系统中运行的一个程序

2.2 线程

1 线程(Thread)是进程的一个执行单元。一个线程就是进程中一个单一顺序的控制流,是进程的一个执行分支。
2 进程是线程的容器,一个进程至少有一个线程,当一个进程中没有线程时,这个进程就结束了。
3 在操作系统中是以进程为单位分配资源。每个线程都有各自的线程栈,自己的寄存器环境,自己的线程本地存储。
4 主线程与子线程:JVM启动时会创建一个主线程,该主线程负责执行main方法。主线程就是运行main方法的线程。Java中的线程是不孤立的,线程之间存在一些联系。如果A线程中创建了B线程,称B线程为A线程的子线程,相应的A线程是B线程的父线程。

2.3 串行、并发、并行

2.3.1串行(Sequential)

一个挨着一个顺序执行,前面的执行完毕后,再执行后面的。效率低。

2.3.2 并发(Concurrent)

一段时间内多个任务都在运行。效率高。

2.3.3 并行(Parallel)

多个任务同时开始,是并发的特殊情况。效率高。
如下图:


image.png

3 创建线程的方法

  • 方法1:继承Thread类
  • 方法2:实现Runnable接口
  • 方法3:实现Callable接口
  • 方法4:使用线程池创建线程

3.1 继承Thread类创建线程

//1:定义类继承 Thread
public class Thread01 extends Thread{
    //2:重写 Thread 父类中的 run()
    @Override
    public void run() {
        System.out.println("子线程");
    }

    public static void main(String[] args) {
        //3)创建子线程对象
        Thread01 t=new Thread01();
        //4)启动线程
        t.start();
        System.out.println("主线程");
    }
}

运行结果:
主线程
子线程
代码分析:

  • 调用线程的start()方法来启动线程。启动线程的实质就是请求JVM运行相应的线程,这个线程具体什么时候运行由线程调度器(Scheduler)决定。
  • start()方法的作用:启动子线程,启动成功的线程会自动调用run()方法。
  • 如果开启了多个线程,start()调用的顺序并不一定就是线程启动的顺序,多线程运行结果与代码执行顺序或调用顺序无关。线程调用具有随机性

3.2 实现Runnable接口创建线程

如果线程类已经有父类,就不能使用继承Thread类来实现线程,此时可以实现Runnable接口来创建线程。

public class Thread03_1 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            System.out.println("sub "+i);
        }
    }

    public static void main(String[] args) {
        Thread03_1 thread03_1 = new Thread03_1();
        Thread thread = new Thread(thread03_1);
        thread.start();
        for (int i = 0; i <100 ; i++) {
            System.out.println("main "+i);
        }
    }
}

3.3 实现Callable接口创建线程

Callable接口内只有一个call方法,所以是函数式接口,能返回线程执行结果,要抛异常,结合FutureTask类获取线程的返回值

class MyThread implements Callable<String>{

    @Override
    public String call() throws Exception {
        for (int i = 0; i <5 ; i++) {
            System.out.println("call i="+i);
        }
        return "callable";
    }
}
public class CallableDemo {
    public static void main(String[] args) {
        //创建线程对象
        MyThread myThread=new MyThread();
        //将线程对象包装到futureTask中,线程返回Stirng类型的值
        FutureTask<String> futureTask=new FutureTask<>(myThread);
        Thread thread=new Thread(futureTask);
        //启动线程
        thread.start();

        String result= null;
        try {
            //获取线程返回结果
            result = (String) futureTask.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        //输出返回结果
        System.out.println(result);
    }
}

运行结果:
call i=0
call i=1
call i=2
call i=3
call i=4
callable

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容