目录
🤣一.线程与进程的概念与联系:
进程的基本概念:
线程的基本概念:
进程和线程的区别与联系:
🙃代码执行实列:
1.通过继承Thread父类来实现多线程
2.通过实现Runnable接口来实现多线程:
3.通过Lambda表达式来实现多线程:
😇Thread类的常见属性和构造方法:
🤣一.线程与进程的概念与联系:
一张漫画,生动阐明进程进程与线程的关系:
进程的基本概念:
- 什么是进程?→
🧐🧐定义:进程是一个具有一定独立功能的程序在一个数据集合上依次动态执行的过程。进程是一个正在执行的程序的实例,包括程序计数器,寄存器和程序变量的当前值。
- 进程有哪些特征?→
1.进程依赖于程序的运行而存在,进程是动态的,程序是静态的
2.进程是操作系统进行资源分配和调度的一个独立单位(CPU除外,线程是处理器任务调度和执行的基本单位);
3.每个进程拥有独立的地址空间,地址空间包括代码区,数据区和堆栈区,进程之间的地址空间是间隔的,互不影响
线程的基本概念:
- 什么是线程?
🦉🦉定义:一个线程就是一个“执行流”,每个线程之间都可以按照顺序执行自己的代码,多个线程之间“同时”执行着多份代码
- 为什么要用到线程?
⾸先, "并发编程" 成为 "刚需":
为了充分利用CPU的资源,避免出现“一核工作,多核围观”的情况,我们可以通过编写特殊的代码,把多个CPU核心,充分利用起来,这样的代码就称为“并发编程”,多进程的编程,就是一种典型的并发编程。虽然多进程能够解决问题,但是随着对于效率的要求越来越高,就希望有更好的方法来实现并发编程。而多进程的编程,最大的问题,就是进程太“重”,创建进程/销毁进程的开销比较大(时间,空间),一旦场景需要频繁的创建和销毁进程,开销就非常明显了→最典型的是服务器开发,针对每一个发出请求的客户端,都创建一个单独的进程,由这个进程负责给客户端提供服务。为了解决进程开销比较大的问题,就发明了线程(Thread),线程可以理解为更加轻量级的进程,也能解决开发并发程序的问题,但是创建/销毁的开销,要比进程更低。
进程和线程的区别与联系:
- 1.进程包含线程:
一个进程里至少包含一个线程(主线程),也可以包含多个线程。不能没有线程
2.进程是系统分配资源的基本单位
3.线程是系统调度执行的基本单位
- 4.同一个进程里的线程之间,共用一份系统资源(内存,硬盘,网络宽带等),尤其是内存资源,就是代码中定义的变量/对象等信息,编程中,多个线程,是可以共用同一份变量的~
- 5.多线程是当下实现并发编程的主流方式,通过多线程,就可以充分利用好多核CPU。但是,也不是线程数目越多,就越好,线程数目达到一定程度,把多个核心都利用充分之后,此时继续增加线程,无法再提高效率,甚至可能会影响效率(线程的调度,也是有开销的)
- 6.多个线程之间,可能会互相影响,线程安全问题。一个线程抛出异常,也可能会把其他线程一起带走
- 7.多个进程之间,一般不会互相影响,一个进程奔溃了,不会影响到其他进程(进程的隔离性)
🙃代码执行实列:
1.通过继承Thread父类来实现多线程
//1.通过继承Thread父类来实现进程
class MyThread extends Thread{
@Override
public void run(){
//这里写的代码,就是即将创建的线程,要执行的逻辑
while(true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//throw new RuntimeException(e);
e.printStackTrace();
}
}
}
}
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
MyThread t = new MyThread();
//创建线程->运行hello main 和 hello thread 并发执行,同时打印
t.start();
//run 不会创建线程,也是再主线程中执行逻辑
//t.run();只循环打印hello thread
while(true){
System.out.println("hello main");
Thread.sleep(1000);
}
}
}
也可以通过匿名内部类来实现:
//通过匿名内部类来创建多线程
public class Demo3 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(){
@Override
public void run(){
while(true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
while(true){
System.out.println("hello main");
Thread.sleep(1000);
}
}
}
运行结果:
2.通过实现Runnable接口来实现多线程:
//2.通过实现Runnable接口来实现多线程
class MyRunnable implements Runnable{
//描述线程里要完成的逻辑是啥
@Override
public void run() {
while(true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Demo2 {
public static void main(String[] args) throws InterruptedException {
MyRunnable runnable = new MyRunnable();
Thread t = new Thread(runnable);
t.start();
while(true){
System.out.println("hello main");
Thread.sleep(1000);
}
}
}
也可以通过匿名内部类来实现:
public class Demo4 {
public static void main(String[] args) throws InterruptedException {
//通过匿名内部类来编写
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while(true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
while(true){
System.out.println("hello main");
Thread.sleep(1000);
}
}
}
3.通过Lambda表达式来实现多线程:
//通过lambda表达式来进行编写
public class Demo5 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while(true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
while(true){
System.out.println("hello main");
Thread.sleep(1000);
}
}
}
😇Thread类的常见属性和构造方法:
- Thread类常见的构造方法:
- Thread类常见的属性:
public class Demo6 {
public static void main(String[] args) {
Thread t = new Thread(()->{
while(true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"自定义线程");//->线程名字为自定义线程
t.start();
System.out.println("线程ID : " + t.getId());
System.out.println("线程名字: " + t.getName());
System.out.println("线程状态: " + t.getState());
System.out.println("线程执行顺序:" + t.getPriority());
}
}
运行结果:
Runnable正在运行,实际上Java没有Running这个线程状态,把正在CPU上运行,和随时可以调度到CPU上运行的,都统称为Runnable
- 前台线程&后台线程
后台线程:如果这个线程执行过程中,不能阻止进程结束(虽然线程执行着,但是进程就要结束了,此时这个线程也会随之被带走)这样的线程就称为“后台线程”
前台线程:如果某个线程执行过程中,能阻止进程的结束,此时这个线程就是“前台线程”
前台线程和后台线程,主要是影响程序的退出
public class Demo7 {
//设置前
public static void main1(String[] args) {
Thread t1 = new Thread(()->{
while(true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
}
//设置后
public static void main(String[] args) {
Thread t2 = new Thread(()->{
while(true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//把 t 设置线程为后台线程(守护线程),不能在阻止程序结束了
t2.setDaemon(true);
t2.start();
}
}
结语: 写博客不仅仅是为了分享学习经历,同时这也有利于我巩固知识点,总结该知识点,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进。同时也希望读者们不吝啬你们的点赞+收藏+关注,你们的鼓励是我创作的最大动力!