🍉作者@ Autumn60
🏄欢迎关注:👍点赞🙌收藏✍️留言
👲微语:每天多一点点努力,不为别的,只为了以后能够多一些选择,选择云卷云舒的小日子,选择自己说了算的生活,选择自己喜欢的人
目录
4.实现Runnable ,使用匿名内部类(定义在类当中的类;)
前言:
上章节小结:
回顾一下上章节所讲,什么是进程?和进程管理
跑起来的程序就是进程;
操作系统会创建一个 PCB ,把这个PCB加入到链表上面,后序遍历这个链表就会获取到当前的链表了。
进程调度:
- 为什么要调度,进程太多了,所以要调度管理.通过快速调度,进程间的来回切换;
- CPU按照并发的方式来执行进程的;
- PCB种提供了一些属性,进程的优先级,进程的状态,进程的上下文,进程的记账信息;
引入进程,目的就是为了能够实现 多个任务,并发执行这样的效果;
进程缺点:
进程有个重大的问题,比较重量,如果频繁的创建/销毁进程,(成本比较高资源分配)
上章要点:
- 线程,进程包括线程;
- 一个进程里面可以有一个线程,或者多个线程;
- 每个线程都是一个独立的执行流,多个线程之间,也是并发执行的;
- 多个线程可能是在多个 CPU 核心上,同时运行;
- 也可能是在一个CPU核心上面,通过快速调度,并行运行;
其实操作系统,真正调度的,是在调度线程,而不进程,前面所述的进程调度: 是指进程里面只有一个线程;
进程是操作系统资源分配的基本单位;
线程是操作系统调度运行的基本单位;
线程轻量的原因
一个进程中的多个线程之间,共用同一份系统资源;
- 内存空间,
- 文件描述符表
只有在进程启动,创建第一个线程的时候,需要花成本去申请系统资源.
一旦进程(第一个线程)创建完毕,此时,后续再创建的线程,就不必再申请资源了,创建/销毁 的效率就提高了不少了;比如创建10个线程干一件事,只需要申请一次资源,而创建10个进程,就需要申请10次资源,就会造成资源的浪费;
一、创建线程
1.1在Java中实现创建线程的五种写法
1.使用Thread ,重写 run方法来创建线程;
代码:
class myThread extends Thread {
@Override
public void run() {
while(true) {
System.out.println("hello t");
}
}
//此刻这里继承 Thread 类
}
public class Demo1 {
public static void main(String[] args) {
Thread t = new myThread();
t.start(); //这里的start就是创建一个新的线程去执行run里面的方法;
while(true) {
System.out.println(" t");
}
}
}
- 这里的 start 就是创建一个新的线程去执行;结果也就是两个循环交替打印;
- 而看代码中run方法 是特殊的方法,会被自动调用到,如果是普通方法,就必须通过手动去调用;
- 如果start 两次的话就会失败;
执行结果:
线程是能够交替运行,但是打印出来的结果肯定是有先有后的,因为是两个线程往同一个控制台上打印,同一个控制台必须得顺序输出~;
再给打印的时候加个sleep 1秒打印一次后的结果:
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
Thread t = new myThread();
t.start();
while(true) {
Thread.sleep(1000); //直接通过类名来调用sleep单位是毫秒
System.out.println(" t");
}
}
}
执行结果:
从图中可以看出来,对于多个线程在CPU上的调度的顺序是 随机的 ,虽然系统的调度是有优先级的,但是这个优先级只能说是''建议'',不是决定;也就是 你说你的, 我做我的;
2.实现 runnable ,重写run方法;
1.创建 Thread 类实例, 调用 Thread 的构造方法时将 Runnable 对象作为 target 参数.
- runnbale 字面意思是可运行的
- 使用 runnalbe描述一个具体的任务;
- 通过run方法来描述;
class myRunnable implements Runnable {
@Override
public void run() {
while(true) {
System.out.println("hello t ");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Demo2 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new myRunnable();
Thread t = new Thread(runnable);
t.start();
while(true) {
Thread.sleep(1000);
System.out.println("sssss");
}
}
}
- 这种写法是使用 Runnable interface 来描述 线程入口; 和第一种起到的效果是一样的;
3.使用集成Thread ,使用匿名内部类
public class Demo3 {
public static void main(String[] args) throws InterruptedException {
//相当于Thread 的子类
Thread t = new Thread() {
@Override
public void run() {
while(true) {
System.out.println("thdsa");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
};
t.start();
while(true) {
System.out.println("aaaaa");
Thread.sleep(1000);
}
}
}
4.实现Runnable ,使用匿名内部类(定义在类当中的类;)
{}大括号放到哪里,就是针对哪个类创建匿名内部类;
代码:
public class Temo4 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
t.start();
while(true) {
Thread.sleep(1000);
System.out.println("11111");
}
}
}
5.lambda 表达式 (本质就是一个匿名函数)
在java中函数(方法),是没有办法脱离类的;而java中,lambda表达式就是一个例外;
小括号里面放的是参数,如果只有一个参数,可以省略,大括号里面放的函数体;,也就是括号里面要执行什么东西;
语法:
()->{
}
1.2 通过软件查看 线程运行情况
通过jdk的软件来查看进程的运行情况:
如果连接失败说明是权限问题,以管理员模式打开即可
连接上之后就可以看到 进程 的 具体的情况了
如果想要看到自己代码的进程,就要保证代码一直在跑,然后打开软件就能查看到了
这种写法是使用 Thread 的 run 描述线程入口;
二、Thread类
- Thread 类,每个线程都有一个唯一的 Thread对象与之关联。
- Java中代码中 Thread 对象 和 操作系统中的 线程是一一对应的;
2.1 Thread 的常见构造方法
这里创建的线程默认是前台的