文章目录
- 什么是线程
- 什么是进程
- 进程的组成
- 什么是pcb
- 进程概括
- 线程
- 线程与进程的关系
- 线程的特点
- 创建线程
- 创建线程方法
- 创建线程的第二种方法
- 对比
- 其他的方式
- 匿名内部类创建线程
- 匿名内部类创建Runable的子类
- lambda表达式创建一个线程
- 多线程的优势
什么是线程
什么是进程
首先想知道什么是线程就得先搞明白什么是进程,关于进程呢,我们说进程是系统进行资源分配的基本单位但是光知道这句话远远不够,因为我们不知道什么是资源分配,我们可以简单的将计算机理解为钱包。
那么资源就是钱包里的钱,至于进程就是我们要做的事情或者说要买的东西,比如说旅游啊买衣服啊。我们把资源(也就是钱)进行了划分,那一部分用来旅游哪一部分用来买衣服做了明确的划分,而这就是资源分配,至于买衣服啊之类的就是我们的进程。
进程的组成
进程是由自己的代码和pcb组成的我们上面说了,进程就是我们要执行的任务,那么在计算机中计算机要执行的任务其实就是我们写的程序,因此我们可以这样理解我们运行了一个程序那么这个程序在我们后台中就是一个进程了。他也正如其名字一样,进行中的程序。由此我们可以知道进程就是我们运行的代码,那么刚刚说的pcb又是什么呢?
什么是pcb
我们运行一个代码那么操作系统就要管理我们运行的程序代码怎么管理呢?那就是先描述再组织,相信大家对这句话应该不陌生吧。那么我们想要描述一个进程该怎么办?就像我们想要描述一个人我们需要把这个人的各种特点记录起来一样,描述进程也是这样把这个进程的各种特点记录下来,而这些特点用一个结构体保存下来这个结构体就是pcb,因此一个进程由什么组成呢?那就是自己的代码+pcb
进程概括
简单来讲进程的概念主要你有两点:
一:进程是一个运行中的实体每一个进程都有自己的内存空间包括堆栈啊等等
二:进程是一个执行的程序,他也需要被管理为了管理它系统中有一个用于存储其基本信息的结构体叫做PCB
线程
什么是线程呢?有了上面的概念我们就可以来讲一下线程了,如果说进程是进行资源分配的基本单位的话那么线程就是**线程是CPU独立运行和独立调度的基本单位。**有些同学可能就蒙了啊什么是cpu独立运行和独立调度呢?我们在购买电子设备的时候我们知道cpu会说他是几核几核的这些核心就是我们用来运行线程的。那么知道这些是不够的,对于初学者来说还是不知道线程到底是什么他跟进程到底有什么关系啊?那么我们现在就来解决一下这个疑惑。
线程与进程的关系
我们上面说了进程就是一个任务,我们去购物,旅游这样的一个任务,那么线程是什么呢?线程则是任务的步骤或者说是任务的分支,就像我们为了完成购物这个任务我们需要分成以下几个步骤那就是第一乘车去商场,第二挑选商品,第三付账,那么以上为了完成这个任务创建的分支就是线程,由此可见线程其实就是进程的分支.那么我们现在就知道为什么了解线程之前要了解进程了。
总结一下目前已知的知识点
线程是进程的一个分支
线程被创建出来是为了执行某个任务
线程是cpu独立运行和独立调度的基本单位.
线程的特点
通过以上的知识我们可以知道线程的哪些特点呢?
线程是轻量级的进程
线程没有独立的地址空间
线程依附于进程进程可以拥有多个线程
创建线程
通过以下的代码来感受以下线程和普通程序的区别吧
class Mytheard extends Thread{
public void run(){
while (true){
try {
sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("我是一个线程");
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException{
Thread ne=new Mytheard();
ne.start();
while(true){
ne.sleep(1000);
System.out.println("Hello world!");
}
}
}
运行截图如下
我们可以看到他跟普通的函数调用不一样的就是主函数和我们创建的这个是在并发执行的这个也就是其中最主要的一个区别.
创建线程方法
在这个代码中呢我们调用了一个start方法.这个方法其实就是创建一个线程并且在创建完成之后呢自动调用我们实现的run函数那么有些同学可能看不出来这到底跟我直接new一个Mythread对象调用这个run有什么区别我们再来看一下下面的代码
class Mytheard extends Thread{
public void run(){
while (true){
try {
sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("我是一个线程");
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException{
Thread ne=new Mytheard();
ne.run();
while(true){
ne.sleep(1000);
System.out.println("Hello world!");
}
}
}
这个代码运行起来呢我们可以发现他是只会执行一个while循环的.并不能做到并发执行,很明显这并不符合我们开发的一个目的.
那么这里面start和run的区别其实就是有没有创建一个线程.而这个方法其实只是我们开发中创建线程的一种方法
创建线程的第二种方法
实现Runable接口
Runable 呢是我们的一个接口,相信未来搞开发的肯定听过一句话叫做高内聚低耦合.而我们的大佬呢考虑到如果将任务和线程的创建绑定在一起就不符合这个高内聚低耦合的精神了为了解耦呢就创建了这样一个方式去创建线程代码如下
class MytheardRunable implements Runnable{
public void run(){
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("我是一个线程");
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException{
Thread t=new Thread(new MytheardRunable());
t.start();
while(true){
Thread.sleep(1000);
System.out.println("Hello world!");
}
}
}
那么这个代码我们发现不同地方除了继承了这个接口之外还有就是我们new对象的时候我们的那里加上了一个参数.我们翻译以下就是创建一个线程对象,并且接下来要执行的任务是这个任务.
我们看一下Thread构造方法的源代码也可以发现这里面也确实有一个参数就是这个接口的参数.
并且我们查看这个接口内部的方法的时候也可以发现这个方法内部也只实现了一个run方法我们也只需要重写一个run方法即可.
对比
对比上面两种方法:
继承 Thread 类, 直接使用 this 就表示当前线程对象的引用.
实现 Runnable 接口, this 表示的是 MyRunnable 的引用. 需要使用 Thread.currentThread()
其他的方式
那么基础较好的同学看到上面的代码可能就会想到别的方式了那就是lamdba和匿名内部类的方式而事实上这两种方式也确实是一种不错的方式去创建线程代码如下
匿名内部类创建线程
public class Main {
public static void main(String[] args) throws InterruptedException{
Thread t=new Thread(){
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("我是匿名内部类创建的一个线程");
}
}
};
t.start();
while(true){
Thread.sleep(1000);
System.out.println("Hello world!");
}
}
}
匿名内部类创建Runable的子类
public class Main {
public static void main(String[] args) throws InterruptedException{
Thread t=new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("我是Runable匿名内部类创建的一个线程");
}
}
});
t.start();
while(true){
Thread.sleep(1000);
System.out.println("Hello world!");
}
}
}
lambda表达式创建一个线程
public class Main {
public static void main(String[] args) throws InterruptedException{
Thread t=new Thread(()->{
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("我是lambda表达式创建出的线程");
}
});
t.start();
while(true){
Thread.sleep(1000);
System.out.println("Hello world!");
}
}
}
多线程的优势
通过上面的例子我们知道了多线程和普通代码区别的就是可以并发执行,那么可以并发执行这就大大的提高了我们的程序运行效率,其实就像我们做事情是一样的,我们可以在做一件事情的同时去做另一个事情并且两个事情互不干扰,效率达到了很大的提升.
和爱的人一起努力.