Java地基(十二)-----线程(一)

进程是什么?

在计算机中,进程代表了内存中正在运行的应用程序,计算机中的资源(cpu 内存 磁盘 网络等),会按照需求分配给每个进程,从而这个进程对应的应用程序就可以使用这些资源了。

线程是什么?

线程是进程中的一个代码执行单元,负责当前进程中代码程序的执行,一个进程中有一个或多个线程。当一个进程中启动了多个线程去分别执行代码的时候,这个程序就是多线程程序。

在这里插入图片描述

并发与并行

并发

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3C3uTkey-1623566728133)(C:\Users\86132\AppData\Roaming\Typora\typora-user-images\image-20210608172906915.png)]

并行:

在这里插入图片描述

抢占式调度

JVM中的线程,使用的为抢占式调度。

常见的调度方式:

  • 时间片轮转
    所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
  • 抢占式调度
    系统会让优先级高的线程优先使用 CPU(提高抢占到的概率),但是如果线程的优先级相同,那么会随机选择一个线程获取当前CPU的时间片。

首发main线程如何去做的?

  • 当前我们使用java命令去运行一个类的时候,会先启动JVM,这个JVM对于计算机来讲,就是一个应用程序,所以同时系统中也会启动一个进程和这个JVM对应。
  • 使用 java 命令来运行一个类的时候,首先会启动JVM(进程),JVM会在创建一个名字叫做main的线程,来执行类中的程序入口(main方法)
public class Test {
	public static void main(String[] args) {
		//获取执行当前方法的线程对象
		Thread currentThread = Thread.currentThread();
		System.out.println("执行当前方法的线程名字为:"+currentThread.getName());
	}
} 
//运行结果:
执行当前方法的线程名字为:main

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uy5b6VJU-1623566728138)(C:\Users\86132\AppData\Roaming\Typora\typora-user-images\image-20210608172508649.png)]

  1. 使用java命令运行Test类,会先启动JVM

  2. 应用类加载器通过CLASSPATH环境变量配置的路径,找到Test.class文件,并加载到方法区。
    注意,这里会同时生产一个Class类型对象,来代表这个Test类型,并且会优先处理类中的静态代
    码(静态属性、静态方法、静态代码块)

  3. JVM创建并启动一个名字叫做main的线程

  4. main线程将Test中的main方法加载到栈区中

  5. 在栈里面,main线程就可以一行行的执行方法中的代码了

  6. 如果在执行代码中,遇到了方法调用,那么线程会继续把被调用的方法,加载到栈中(压栈操
    作),然后执行栈顶这个最新添加进来的方法,栈顶方法执行完,就释放(出栈操作),然后在
    进行执行当前最新的栈顶方法(之前我们画过栈里面的方法调用图,例如在异常的学习过程中)

  7. 代码执行过程输出执行结果

  8. 当前是单线程程序,main线程结束了,JVM就停止了,如果是多线程程序,那么JVM要等所有线程
    都结束了才会停止

其他的线程是如何去创建的

Java中通过继承Thread类来创建并启动一个新的线程的步骤如下:

  1. 定义 Thread 类的子类(可以是匿名内部类),并重写 Thread 类中的 run 方法, run 方法中的代码就是线程的执行任务

  2. 创建 Thread 子类的对象,这个对象就代表了一个要独立运行的新线程

  3. 调用线程对象的 start 方法来启动该线程

直接匿名内部类创建

public class Test {
	public static void main(String[] args) {
		Thread t = new MyThread(){
			@Override
			public void run() {
				System.out.println("端茶")
			}
		};
	t.start();
	}
}

首先我们要知道我们创建的线程与main线程的区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-szq69rLJ-1623566728140)(C:\Users\86132\AppData\Roaming\Typora\typora-user-images\image-20210608173624282.png)]

我想以上俩张图可以说明,创建新线程是创建一个新得栈区,而之前的是只在一个main线程上使用

  • 注意1,之前所提到的栈区,又被称为方法调用栈,是线程专门执行方法中代码的地方,并且每一个线程,都有自己独立的栈空间,和别的线程相互不影响
  • 注意2,最先启动的线程是主线程(main线程),因为它要执行程序的入口main方法,在主线程中,创建并且启动了t线程,启动之后main线程和t线程将各自独立运行,并且争夺CPU的时间片
  • 注意3,线程启动之后(调用start方法),会开始争夺CPU的时间片,然后自动执行run方法,如果子类对象重写了,那么就调用到重写后的run方法

Runnable接口:线程代码入口

Thread 类也是 Runnable 接口的实现类

该接口中只有一个抽象方法 run

public class Test {
	public static void main(String[] args) {
	//Runnable接口的实现类中,重写了run方法,指定线程的执行任务
		Runnable run = new Runnable() {
			@Override
			public void run() {
				System.out.println("端茶")
			}
		};
	//创建线程对象,指定执行任务
	Thread t = new Thread(run);
    t.start();
	}
}

意义:

初看和直接创建Thread没什么区别都是重写run方法调用start方法去运行,可是直接创建Thread方法的话就一个线程只能完成一个任务,而使用Runnable的话当你需要什么方法就传给线程Runnable创建的run方法,使得代码更加的灵活,耦合度降低。

线程名字的获取

创建出来的线程会有一个默认的名字是由Thread的构造器初始化的

public Thread() {
	init(null, null, "Thread-" + nextThreadNum(), 0);
}
自定义名字

Thread t = new Thread("t线程");

或者

Thread t = new Thread();
t.setName("t线程");

又或者

Thread t = new Thread(new Runnable(){
	public void run(){
	//执行任务
	}
},"t线程");
查看名字

Thread.currentThread().getName();获取当前线程的名字的方法

public class Test {
	public static void main(String[] args) {
		String name = Thread.currentThread().getName();
		System.out.println("执行当前main方法的线程是:"+name);
		Runnable run = new Runnable() {
			@Override
			public void run() {
				String name = Thread.currentThread().getName();
				System.out.println("执行当前run方法的线程是:"+name);
			}
		};
    	Thread t = new Thread(run);
		t.start();
	}
} 
//运行结果为:
执行当前main方法的线程是:main
执行当前run方法的线程是:Thread-0

多线程的优点

1.资源利用率更好
2.程序设计在某些情况下更简单
3.程序响应更快

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值