学习线程之前

一.首先要先了解什么是并发和并行;

并发:指的是两个或者n个事情在同一个时间段内发生,也就是说,如果两个事情在同一个小时内发生,比如在上午十点到十一点之间的一个小时我在踢球和Tom在弹钢琴这两件事情就是并发发生(也可以说是交替执行,比如吃饭,吃一个菜后再吃另一个菜)

并行:指的是同一时刻两件事情同时发生,比如,在十点整这一刻,我在踢球,你在睡觉叫做并行。(一口吃了两个菜,同时执行)

进程的概念:是指在内存中运行的应用程序,例如双击打开一个软件,它就会进入内存中成为一个进程(你的输入法也是一个进程)

线程的概念:进程的基本执行单元,例如你打开一个杀毒软件,它会进入内存成为一个进程,然后它对应有多个功能(查杀木马,清理垃圾等,)也就可以把这些一个个功能当做一个个线程。一个进程至少含有一个线程(N功能≈N线程)。

总结:一个程序至少有一个进程,一个进程至少有一个线程

说到线程,可以拓展到CUP

比如一个CPU是4核8线程的CPU,证明它可以同时运行8个线程(也就说速度越快,可以同时执行8功能),线程就是进程中执行功能的时候一条通往CPU的道路(要执行某些程序就需要一条通往CPU的通道,也就是需要向CPU请求占用CPU)

单核心单线程CPU:虽然可以执行同时多个线程(看似),实际上是CPU在疯狂切换路径(并发),一个线程执行一会儿(1/n毫秒)




java 使用主线程执行 java主线程获取子线程数据_java 使用主线程执行


如果是8线程CPU,就不需要切换,因为它可以同时执行8个线程

二.线程的调度

1.分时调度:线程轮流使用CPU,例如上面的单核单线程,就是每个线程使用1/n毫秒,来回切换

2.抢占式调度:谁的优先级高,就先执行谁(Java就是抢占式调低,谁抢夺CPU厉害就谁用)

三.主线程

主线程:执行主(main)方法的线程

单线程程序:java程序中只有一个线程 (在没学线程之前你的程序一般就是单线程程序)

执行从main方法开始从上到下依次执行

单线程程序如下(主线程程序)


java 使用主线程执行 java主线程获取子线程数据_主线程_02


java 使用主线程执行 java主线程获取子线程数据_单线程_03


//创建一个对象演示main线程
public class Person {
    private String name;


    public Person(String name) {
        this.name = name;
    }
    public void run(){//输出20次
        for (int i = 0; i < 20; i++) {
            System.out.println(this.name+i);
        }
        }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


main方法


public class MainThread {
    public static void main(String[] args) {
        Person p=new Person("小强");
        p.run();
    }
}


那主线程是怎么回事呢?

JVM执行main方法的时候,main方法会进入栈内存,这个时候要获得CPU才能够获得执行的权利,JVM就会找到操作系统开辟一条从main方法


java 使用主线程执行 java主线程获取子线程数据_java 使用主线程执行_04


通向CPU的道路(也就是创建了一个进程,叫做主线程),这样CPU才会执行main方法,当你在main方法里面输入0/0报错,系统就会提示你是


java 使用主线程执行 java主线程获取子线程数据_单线程_05


Exception in thread "main",在主线程的异常。

四.如何创建线程?

创建线程类:(创建多线程程序)

Java虚拟机运行应用程序(并发)得运行多个线程。

第一种创建线程的方法:Thread类

Thread类存在于lang包下,我们要创建一个新的线程

1.要创建一个类继承Thread类(创建Thread的子类)

2.在这个子类下重写run()方法,在里面写入你要这个类执行的代码(设置你的线程任务(表明要干什么))

3.创建Thread类的子类对象

4.调用star()方法开启新线程,star()方法会自动调用run()方法(也就是执行线程任务)

实例:1.创建了一个Student作为Thread的子类(也就是继承),并且在Student类里面重写了run()方法,2.在MyThread类里面创建了个主方法,然后创建子类Student类对象,调用star()方法,开启线程并且使得任务代码(run()方法里面的代码)执行, 并且在main方法里面写了一段代码(main线程),用来查看线程的输出。(两线程代码)


java 使用主线程执行 java主线程获取子线程数据_main方法_06

Student类继承Thread

java 使用主线程执行 java主线程获取子线程数据_主线程_07

MyThread用来创建对象开启线程输出结果

java 使用主线程执行 java主线程获取子线程数据_主线程是如何向子线程传递数据的?_08

执行结果

代码如下:


//创建一个Student类继承Thread,也就是说要用这个Student类来开启新线程执行任务
public class Student extends Thread {

    @Override
    public void run() {//重写run方法,写你要的执行代码
        for (int i = 0; i < 50; i++) {
            System.out.println("小黄------->疯狂学习"+i);
        }
    }
}


代码2:


public class MyThread {
    public static void main(String[] args) {
        Student one=new Student();//3.创建Thread的子类对象
        one.start();//4.子类对象调用star方法开启新线程,调用run方法

        for (int i = 0; i < 50; i++) {//创建一个主线程输出
            System.out.println("main线程---->"+i);
        }

    }
}


为什么看到的结果交替执行?

上面有说到java是抢占式执行的,谁的优先级高就谁先执行,谁抢到CPU就谁先执行,所以可以看到线程的结果是打乱的,不是你决定而是由系统决定谁先执行,因此就出现了主线程和我开启的0线程在争夺CPU导致输出混乱。每次执行代码的结果都会不一样!

创建线程的第二种方式:

创建接口Runnable的实现类

第一步:创建一个Runnable的实现类并且重写run方法设置线程任务,

第二步:new一个Thread类,然后往里面传递一个Runnable类(主要是Runable类没有start方法开启多线程),Thread类的构造方法里面可以传递一个Runnable类

第三步:调用start方法开启多线程


java 使用主线程执行 java主线程获取子线程数据_main方法_09

Runnable接口实现类

//创建一个Runnable的实现类
public class Runableimpl implements Runnable{
    @Override
    public void run() {//和第一种方法一样重写run方法设置线程任务
        for (int i = 0; i < 50; i++) {
            System.out.println("实现Runnable开启多线程");
        }
    }
}


java 使用主线程执行 java主线程获取子线程数据_主线程_10


public class Demo01Runnable {
    public static void main(String[] args) {
        Runnable run=new Runableimpl();//多态实现接口创建Runnable
        Thread t0=new Thread(run);//创建线程对象传入Runnable类对象
        t0.start();//调用start方法开启线程
    }
}