当前位置: 首页 > news >正文

网站建设有限公司每天看七个广告赚40元的app

网站建设有限公司,每天看七个广告赚40元的app,正规网购平台有哪些,wordpress旅游公司主题大家好呀 我是浪前 今天给大家讲解的是创建线程以及线程的属性 祝愿所有点赞关注的人,身体健康,一夜暴富,升职加薪迎娶白富美!!! 点我领取迎娶白富美大礼包 🍓多线程编程: 前言: 我们为什么不用多进程?…

在这里插入图片描述

大家好呀
我是浪前

今天给大家讲解的是创建线程以及线程的属性

祝愿所有点赞关注的人,身体健康,一夜暴富,升职加薪迎娶白富美!!!
点我领取迎娶白富美大礼包

🍓多线程编程:

前言:
我们为什么不用多进程?

多进程相关的API在Java标准库中没有提供
Java适合使用多线程来进行编程:

多线程在并发编程的时候,效率更高
尤其对于Java进程是要启动Java虚拟机来说
启动虚拟机这个事情开销很大, 搞多个Java进程就是搞多个Java虚拟机

于是java使用了标准库把与多线程编程有关API给封装了

比如在Java中的Thread类

一个进程中至少有一个线程
这个进程中的第一个线程就叫做主线程

main方法就是主线程的入口方法

每个线程都是一个独立的执行流,相互独立执行,互不干扰

线程的执行顺序是不确定的,是随机的

为什么这里是随机的呢?
因为操作系统中有一个调度器模块,这个模块的实现方式就是类似于一种随机调度的效果

🍓随机调度:

一个线程什么时候被调度到CPU上执行,时机是不确定的
一个线程什么时候从CPU上下来,给别的线程让位, 时机也是不确定的

随机调度这种也叫抢占式执行:
这个特性会导致多线程安全问题

Windows等等主流的操作系统都是抢占式执行

🍓观看线程的详细信息:

使用一个程序来观看线程的详细信息
在jdk中的bin目录之下有一个jconsole.exe的程序
在这里插入图片描述

在这里插入图片描述

在使用这个jconsole.exe程序查看线程的详细信息之前要先确保两个点:

  1. 确保你的程序(线程)已经先跑起来了
  2. 有些需要使用管理员方式来运行

如图所示:
在这里插入图片描述

在这里插入图片描述

🍓sleep

线程中的while循环转得太快了, 使用sleep方法来休眠,使得循环转得慢一些,
sleep是Thread的静态方法, 属于Thread类

我们可以在线程中加入sleep 来降低循环速度

在这里插入图片描述
时间单位换算:
1s = 1000ms
1 ms = 1000us
1us = 1000ns

🍓创建线程

线程的创建有好几种方式:

  1. 继承Thread类, 重写run方法
  2. 实现Runnable接口
  3. 还是继承Thread,重写run,但是使用匿名内部类
  4. 还是实现那Runnable, 重写run, 也是使用匿名内部类
  5. 基于Lambda表达式)最推荐的方式

🍓第一种: 继承Thread类, 重写run方法:

class MyThread extends Thread{  @Override  public void run(){  while(true){  System.out.println("hello thread");  try {  Thread.sleep(1000);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }  
}  public class ThreadDemo01 {  public static void main(String[] args) throws InterruptedException {  Thread t = new MyThread();  t.start();  while (true) {  System.out.println("hello main");  Thread.sleep(1000);  }  }  
}

结果如图所示:
在这里插入图片描述

🍓第二种:实现Runnable接口

class MyRunnable implements Runnable{  @Override  public void run(){  System.out.println("hello Runnable");  try {  Thread.sleep(2000);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  
}  public class Text2 {  public static void main(String[] args) throws InterruptedException {  Thread t2 = new Thread(new MyRunnable());  t2.start();  while(true){  System.out.println("hello main");  Thread.sleep(2000);  }  }  
}

结果如图所示:
在这里插入图片描述

🍓注意事项:

我们使用Runnable接口的方式和直接继承Thread类的方式有什么区别吗?
我们使用Runnable接口的方式有利于我们进行解耦合

🍓解耦合:

那什么是解耦合?
我们在创建一个线程,是需要两个关键操作的:

  1. 明确线程要执行的任务
  2. 调用系统的API创建出线程

那么此时若我们使用的是Runable接口
那么我们就可以把任务单独提取出来,提取出来之后

就可以随时把代码改成使用其他方式来执行这个任务

举个例子:
现在有一个一家三口,父亲,母亲,和儿子,现在家里面没有酱油了,此时就需要去执行“买酱油”这个任务

那么我们就可以把“买酱油”这个任务单独提取出来,之后这个任务是交给父亲执行,还是母亲执行,还是儿子执行都是没有本质区别的

而在代码中就是把这个任务单独提取成Runnable, 后续是谁来执行都可以进行轻松的调整
这个就是解耦合

🍓Runnable

Runnable可以理解为可执行的
作用:

通过这个接口就可以抽象表示出一段可以被其他实体来执行的代码~~

在代码中的run方法就是这个Runnable要表示的一段代码

class MyRunnable implements Runnable{  @Override  public void run(){  System.out.println("hello Runnable");  try {  Thread.sleep(2000);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  
}

但是这个Runnable只是一段可以执行的代码,还是要搭配Thread类,才能够真正地在系统中创建出线程
就是把线程和要执行的任务进行了解耦合:
如下所示:

Thread t = new Thread(new MyRunnable());

🍓第三种 : 继承Thread类, 重写run方法,使用匿名内部类:

匿名内部类 :

在一个类中定义的类,没有名字, 也就不能够重复使用,用一次就扔了

这个匿名内部类是Thread的子类, 同时又把这个匿名内部类的实例给创建出来

而且这个匿名内部类是可以重写run方法的

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);  }  }  
}

🍓第四种: 实现Runnable接口, 重写run, 使用匿名内部类

public class Demo4 {  public static void main(String[] args) throws InterruptedException {  Runnable runnable = new Runnable() {  @Override  public void run() {  while (true) {  System.out.println("hello thread");  try {  Thread.sleep(1000);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }  };  Thread t = new Thread(runnable);  t.start();  while(true){  System.out.println("hello main");  Thread.sleep(1000);  }  }  
}

🍓第五种: 基于Lambda表达式(最推荐的方式)

Lambda表达式是更简洁的语法表示方式: (语法糖)

以下就是一个for循环的语法糖

for(int x : arr)

Lambda表达式如下:

Thread t= new Thread(() -> {
});

Lambda表达式:

Lambda表达式是一个匿名函数, (无名函数; 一次性的)
主要是用来实现回调函数的效果的

回调函数:

回调函数 :

不是程序员主动调用, 也不是现在立即调用
而是把调用的机会交给别人(操作系统, 库, 框架, 别人写的代码)
交给别人之后在合适的时机来进行调用

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(String name) :

name不会影响到线程的执行, 就只是给线程取不同的名字;为了方便调用和调试
而且线程间的名字是可以重复的,但是要起一个有意义的名字

例子:
创建一个线程, 命名为 " 这个是一个新线程"

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);  }  }  
}

在这里插入图片描述

getId() :

JVM自动分配的身份标识,会保证唯一性, 标识一个进程中唯一的一个线程
这个ID是java给你这个线程分配的ID, 不是系统API给你分配的, 也不是PCB中的ID

getState() :

线程的状态,显示线程是就绪状态还是阻塞状态)

getPriority() :

线程的优先级: 由于系统是随机调度的方式
在java中设置优先级效果不明显;只是对内核调度器的调度过程产生了一些影响:

isDaemon():

描述当前线程是否是守护线程:(后台线程)

t.setDaemon(true); //设置为后台线程

不写这个代码就默认是前台线程

🍓前台线程与后台线程的区别:

后台线程: 后台线程运行不会阻止进程结束

前台线程: 前台线程运行会阻止进程结束

我们创建的代码默认是前台线程,在运行过程中会阻止进程结束
只要前台进程没有执行完毕,那么进程就不会结束
即使main方法已经执行完毕了,进程也不会结束

如下图所示:

在这里插入图片描述

在这里插入图片描述

isAlive() :

表示内核中的线程(PCB)是否存在

java代码中定义的线程对象(Thread) 实例, 虽然表示一个线程
但是这个对象本身的生命周期和内核中PCB的生命周期不完全一样

Thread t = new Thread()

此时t对象有了,但是内核PCB还没有,isAlive 就是false

当执行了下面的代码之后,才创建了PCB:

t.start();

此时才有了内核PCB, 才真正的在内核中创建了这个PCB, 此时isAlive() 就是true

在这里插入图片描述

start()

Thread类使用start方法来启动一个线程

对于同一个Thread类来说, start()方法只能够调用一次

在这里插入图片描述

🍓start() 和 run() 方法的区别

有一个经典的面试题:
start() 和 run() 方法的区别是什么?

如果是调用run()方法来执行, 那么就没有创建新的线程
在代码中只有main这个主线程, 在代码中只有一个线程,
此时这个主线程就只能够停留在run方法中的循环里面, 一直打印hello thread

不会去执行mian方法中下方的while循环的代码,也就不会打印hellow main

如图:
在这里插入图片描述

那如果是调用的start() 方法来执行代码,则会创建一个新的线程

而这个新的线程就会去执行run()方法中的循环, 来打印hellow thread
而main方法中的主线程就会去继续向下执行下方的while循环中的代码了

也就会在循环中不断地打印hellow main , 此时是有两个线程同时执行的,

第一个是通过start()创建出来的新线程 在打印run()方法中代码
第二个是main主线程在执行while循环中的代码

如图:
在这里插入图片描述

🍓总结:

两者的区别如下:

start方法的内部是调用系统的API
在系统内核中创建出线程,然后再由这个线程去执行run方法

run方法是单纯描述了这个线程的要执行什么内容
这个run方法会在start方法创建好线程之后自动被调用
没有创建出新的线程, 只是一个run方法

在这里插入图片描述

http://www.shuangfujiaoyu.com/news/2538.html

相关文章:

  • 网门网站下载地址广告联盟平台挂机赚钱
  • 全屋定制品牌推荐重庆百度快速优化
  • 猪八戒官网做网站专业吗哪家网站推广好
  • 廊坊网站制作潍坊公司电话2021百度新算法优化
  • 聊城app制作网站百度有刷排名软件
  • 网站推广主要怎么做舆情管理
  • 便宜建网站seo关键字优化教程
  • 有没有99块钱做网站爱站网ip反查域名
  • 皮肤测试网站怎么做seo外贸推广
  • java制作的网站开发百度精简版网页入口
  • 云南网站建设维修公司哪家好兰州seo新站优化招商
  • 深圳民治网站建设长沙网站优化对策
  • 沈阳网站关键词优化做的好吗代运营
  • 学室内设计网站如何自己建网站
  • 提高网站权重工具搜索引擎优化常用方法
  • wordpress禁用文章修订版四川百度推广和seo优化
  • 大兴建站推广公众号seo排名
  • 奉贤网站制作互联网公司排名2021
  • 怎么做营销型网站百度人工客服电话
  • wordpress标题怎么改杭州网站推广与优化
  • 我要看一集片做网站珠海seo关键词排名
  • 独立网站b2c短视频营销推广
  • 用frontpage做网站百度seo提高排名费用
  • 西安做百度推广网站 怎样备案西安网站托管
  • 百度做的网站首页在线客服修改免费企业网站建设流程
  • 洛阳做网站公司哪家好如何在百度投放广告
  • 360个人网站建设郑州百度seo
  • dw做的上传网站打不开最新军事消息
  • 网站建设如何插音乐西安排名seo公司
  • 哪些网站做二手挖机保定百度推广优化排名