学习线程之前
一.首先要先了解什么是并发和并行;
并发:指的是两个或者n个事情在同一个时间段内发生,也就是说,如果两个事情在同一个小时内发生,比如在上午十点到十一点之间的一个小时我在踢球和Tom在弹钢琴这两件事情就是并发发生(也可以说是交替执行,比如吃饭,吃一个菜后再吃另一个菜)
并行:指的是同一时刻两件事情同时发生,比如,在十点整这一刻,我在踢球,你在睡觉叫做并行。(一口吃了两个菜,同时执行)
进程的概念:是指在内存中运行的应用程序,例如双击打开一个软件,它就会进入内存中成为一个进程(你的输入法也是一个进程)
线程的概念:进程的基本执行单元,例如你打开一个杀毒软件,它会进入内存成为一个进程,然后它对应有多个功能(查杀木马,清理垃圾等,)也就可以把这些一个个功能当做一个个线程。一个进程至少含有一个线程(N功能≈N线程)。
总结:一个程序至少有一个进程,一个进程至少有一个线程
说到线程,可以拓展到CUP
比如一个CPU是4核8线程的CPU,证明它可以同时运行8个线程(也就说速度越快,可以同时执行8功能),线程就是进程中执行功能的时候一条通往CPU的道路(要执行某些程序就需要一条通往CPU的通道,也就是需要向CPU请求占用CPU)
单核心单线程CPU:虽然可以执行同时多个线程(看似),实际上是CPU在疯狂切换路径(并发),一个线程执行一会儿(1/n毫秒)
如果是8线程CPU,就不需要切换,因为它可以同时执行8个线程
二.线程的调度
1.分时调度:线程轮流使用CPU,例如上面的单核单线程,就是每个线程使用1/n毫秒,来回切换
2.抢占式调度:谁的优先级高,就先执行谁(Java就是抢占式调低,谁抢夺CPU厉害就谁用)
三.主线程
主线程:执行主(main)方法的线程
单线程程序:java程序中只有一个线程 (在没学线程之前你的程序一般就是单线程程序)
执行从main方法开始从上到下依次执行
单线程程序如下(主线程程序)
//创建一个对象演示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方法
通向CPU的道路(也就是创建了一个进程,叫做主线程),这样CPU才会执行main方法,当你在main方法里面输入0/0报错,系统就会提示你是
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线程),用来查看线程的输出。(两线程代码)
Student类继承Thread
MyThread用来创建对象开启线程输出结果
执行结果
代码如下:
//创建一个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方法开启多线程
Runnable接口实现类
//创建一个Runnable的实现类
public class Runableimpl implements Runnable{
@Override
public void run() {//和第一种方法一样重写run方法设置线程任务
for (int i = 0; i < 50; i++) {
System.out.println("实现Runnable开启多线程");
}
}
}
public class Demo01Runnable {
public static void main(String[] args) {
Runnable run=new Runableimpl();//多态实现接口创建Runnable
Thread t0=new Thread(run);//创建线程对象传入Runnable类对象
t0.start();//调用start方法开启线程
}
}