多线程(1)——熟悉线程

打印 上一主题 下一主题

主题 1818|帖子 1818|积分 5454

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x

在先容多线程前,先先容一下操作系统的概念
操作系统是一个管理的软件
1.对下管理各种硬件装备
2.对上给软件提供稳固的运行环境
概念

线程是什么

一个线程就是一个“执行流”,每个线程之间都可以按照顺序执行本身的代码,多个线程之间同时执行着多份代码
线程过多,因为CPU核心书名是有限的,这些线程在CPU上的调理开销会越来越明显,也会影响服从
所以要根据CPU资源合理增加线程数量
为什么要有线程

历程和线程的区别

历程是运行起来的步伐,每个历程通过链表连接起来,历程有两种状态 并发(一个CPU核心同时执行一个线程,但因为运行/切换速度极快,可以看做是同时在执行多个线程) 和 并行(两个CPU核心同时执行两个线程) ,而每个历程中 有多个 线程,这些线程共用该历程的资源(内存资源,文件描述符表),每个线程都可以独立执行一段逻辑,而且独立在 CPU 上调理
当历程已经有了,在历程内部再创建新线程,就把申请资源开销省下来了
历程包含线程(一个历程至少有一个线程,对于Java步伐中,main方法所在的线程就是主线程)
   历程是操作系统资源分配的基本单位
线程是操作系统调理执行的基本单位
  Java的线程 和 操作系统线程 的关系

线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 而且对⽤⼾层提供了⼀些 API(Java内部的方法) 供⽤⼾
使⽤(比方 Linux 的 pthread 库).
Java 标准库中 Thread 类(线程)可以视为是对操作系统提供的 API 进⾏了进⼀步的抽象和封装,而历程封装的很粗糙,多历程变成的许多本领,JVM原生API没有提供,本身Java设计者就不鼓励多历程编程
创建线程

方法1:继承Thread 类

  1. class myThread extends Thread{
  2.     @Override
  3.     public void run(){
  4.         while(true){
  5.             System.out.println("Hello, Thread!");
  6.             try {//这里只能用try catch ,因为父类Thread的run方法没有抛出异常,子类myThread的run方法也不能抛出异常
  7.                 //如果这里用throws,父类和子类方法声明就不一致,就不满足重写的要求
  8.                 Thread.sleep(1000);
  9.             } catch (InterruptedException e) {
  10.                 // TODO Auto-generated catch block
  11.                 e.printStackTrace();
  12.             }
  13.         }
  14.     }
  15. }
  16. public class Demo1 {
  17.     public static void main(String[] args) throws InterruptedException {
  18.         Thread thread=new myThread();
  19.         //thread.start();
  20.         thread.run();//如果这里调用run方法,就不会启动线程,而是在main线程中执行run方法,不会并行执行
  21.         while (true) {
  22.             System.out.println("Hello, main!");
  23.             Thread.sleep(1000);
  24.         }
  25.     }
  26. }
复制代码
注意,上述线程运行时myThread线程和main线程在操作系统中的调理顺序是无序,不可预测的,是随机的。即大概会先打印 Hello, Thread!,也大概先打印 Hello, main!
run和start方法

   在上述方法中,重写的是Thread的run方法,但是在main方法中调用的是start方法,这么做的原因是:
start方法是调用系统的API(Java 当地方法(封装了对系统底层的调用)),它才是真正在操作系统内部创建一个线程
这个新的线程就会以run方法为入口(执行run中的逻辑)
run方法不需要代码中显示调用,run 方法执行完成后线程进入销毁阶段。
  如果在main中直接调用thread.run(),就没有创建新的线程,而是直接在main方法所在的 主线程 中执行了run的逻辑。如果在main中调用thread.start(),就会开启一个新线程和main线程并发执行
方法2:实现Runnable 接口

实现Runnable接口的方式,是把线程的任务单独提取出来,放到一个类中,然后再创建线程时,把这个类的实例作为参数传递给Thread的构造方法。这样,线程的任务就被封装到了一个类中,使得代码更加清楚,也便于维护和扩展。
  1. class MyRunnable implements Runnable{
  2.     @Override
  3.     public void run(){
  4.         while (true) {
  5.             System.out.println("hello thread");
  6.             try {
  7.                 Thread.sleep(1000);
  8.             } catch (InterruptedException e) {
  9.                 e.printStackTrace();
  10.             }
  11.         }
  12.     }
  13. }
  14. public class Demo2 {
  15.     public static void main(String[] args) throws InterruptedException {
  16.         /*
  17.         
  18.          */
  19.         Runnable runnable=new MyRunnable();
  20.         //runnable没有start方法,项启动线程要搭配Thread
  21.         Thread thread=new Thread(runnable);
  22.         thread.start();
  23.         while (true) {
  24.             System.out.println("hello main");
  25.             Thread.sleep(1000);
  26.         }
  27.     }
  28. }
复制代码
方法1和方法2的区别

对于第一种写法(继承thread类),描述任务的时候,认为代码是写到Thread子类中的
此时任务内容 和 Thread 类的耦合度更高
第二种方法,任务写到Runnable中,不涉及到线程相干的概念,任务内容和Thread的耦合度很小,险些没有,这个任务就能放进其他来执行(历程,协程)
耦合度:在编码中,更倾向于写耦合度低的代码,方便修改,使用
方法3:通过匿名内部类继承Thread

  1. Thread thread=new Thread(){//创建了一个没有名字的匿名内部类
  2.             public void run(){
  3.             }
  4.         };
复制代码
使用举例
  1. public class Demo3 {
  2.     public static void main(String[] args) {
  3.         Thread thread=new Thread(){//创建了一个没有名字的匿名内部类
  4.             //这个类是Thread的子类,子类重写了run方法
  5.             //同时也创建了子类实例,通过 thread 指向
  6.             public void run(){
  7.                 while (true) {
  8.                     System.out.println("hello thread");
  9.                     try {
  10.                         Thread.sleep(1000);
  11.                     } catch (InterruptedException e) {
  12.                         e.printStackTrace();
  13.                     }
  14.                 }
  15.             }
  16.         };
  17.         thread.start();
  18.     }
  19. }
复制代码
像这样的写法的目的就是为了简化代码
方法4:通过匿名内部类实现Runnable,重写run,搭配Thread

  1. public class Demo4 {
  2.     public static void main(String[] args) {
  3.         Runnable runnable=new Runnable() {
  4.             @Override
  5.             public void run() {
  6.                 while (true) {
  7.                     System.out.println("hello thread");
  8.                     try {
  9.                         Thread.sleep(1000);
  10.                     } catch (InterruptedException e) {
  11.                         e.printStackTrace();
  12.                     }
  13.                 }
  14.             }
  15.         };
  16.         Thread thread=new Thread(runnable);
  17.         thread.start();
  18.     }
  19. }
复制代码
方法5:基于Lambda表达式创建Thread

语法:
  1. Thread thread=new Thread(()->{/*此处写run方法内容*/});
复制代码
lambda表达式,本质上是 匿名方法
直接使用 lambda 作为入口方法
使用举例:
  1. public class Demo5 {
  2.     public static void main(String[] args) {
  3.         Thread thread=new Thread(()->{
  4.             while(true){
  5.                 System.out.println("hello thread");
  6.                 try {
  7.                     Thread.sleep(1000, 0);
  8.                 } catch (InterruptedException e) {
  9.                     e.printStackTrace();
  10.                 }
  11.             }
  12.         });
  13.         thread.start();
  14.     }
  15. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大连密封材料

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表