2024年C C++最新java多线程编程_Thread类_线程状态的理解_java thread serial,带你一步一步深入Handler源码

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

我们知道操作系统中的线程是并发执行的!
Thread类是java给我们提供的一个类,通过Thread可以实现java并发编程!Thread类可以视为java标准库提供的API
创建好的Thread实例和操作系统的线程一一对应!!!

Thread是在java.lang包下的类无需导入!!!

了解并发编程

public class Thread\_4 {
  public static void main(String[] args) {
  //自己创建的线程t1
      Thread t1 = new Thread(()->{
          while (true){
              System.out.println("hello Thread!");
              try {
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      });
      t1.start();//执行t1
      while (true){
          //主线程 main线程 一个java进程中自动创建了main线程!!!
          System.out.println("hello main");
          try {
              Thread.sleep(1000); //睡眠1s 阻塞线程!在这1s不然上cpu
          }catch (InterruptedException e){
              e.printStackTrace();
          }
      }
  }

}

``

在这里插入图片描述
我们可以看到t1线程和main并发执行!这里的并发包括并发和并行!
我们也不知道cup啥时候让这两个线程并发,啥时候并行!
这些都是操作系统的调度问题!!!

多线程优势

当我们要同时自增两数时,采用多线程编程和单线程编程又有啥区别呢,让我们看看下方代码就知道了!

//自增两数
public class Thread\_8 {
  private static final long count=100\_0000\_0000L;
  public static void main(String[] args) throws InterruptedException{
          concurrent();//多线程并行执行
          serial(); //单线程串行执行

  }
  public static void concurrent() throws InterruptedException {
      //多线程
      long beign = System.nanoTime();//获取当前时间戳毫秒数
      Thread t1 = new Thread(()->{
          long a = 0;
          for (int i = 0; i < count; i++) {
              a++;
          }
      });
      t1.start();
      long b = 0;
      for (int i = 0; i < count; i++) {
          b++;
      }
      t1.join();
      long end = System.nanoTime();//获取结束时间戳
      System.out.println("并行:"+(end-beign));
  }
  public static void serial(){
      long begin = System.nanoTime();
      long a = 0;
      for (int i = 0; i < count; i++) {
          a++;
      }
      long b = 0;
      for (int i = 0; i < count; i++) {
          b++;
      }
      long end = System.nanoTime();
      System.out.println("串行:"+(end-begin));
  }
}

在这里插入图片描述

  • 我们并不知道何时并发的两个线程是并行还是并发,这都是取决于线程的调度器的调取问题!
  • 并发编程也不一定比串行快,如果自增的两数较小,创建变量的时间占据该线程执行的大部分时间,那么就达不到并发编程的优势!
  • 是否采用多线程编程视情况而定,并非无脑多线程!

一个java进程中自动会创建一个main线程!!!并在操作系统有对应该线程!

我们如何查看线程是否在操作系统中创建成功呢?
我们再jdk中的lib文件夹下打开jconsole.jar文件便可以查看线程!!!
在这里插入图片描述
我们打开便可以看到我们创建的java线程以及jvm自带的一些线程!!!

创建Thread实例

  • 方法一
    创建Thread子类,重写run方法
class Mythread extends Thread{
    @Override
    public void run() {//描述线程要执行的任务!
        System.out.println("run");
    }
}
public class Thread\_1 {
    public static void main(String[] args) {
        Thread t1 = new Mythread();
        t1.start();
    }
}

这里的run只是描述该线程需要执行那些任务!这只是创建了一个类! 线程的执行需要该线程实例执行start方法!执行start方法后操作系统才会创建对应的线程!
在这里插入图片描述

  • 方法二
    创建一个类实现Runnable接口,重写run方法,再将该类传参到创建Thread对象的构造方法!
class MyRun implements Runnable{
    @Override
    public void run() {
        //描述任务
        System.out.println("实现Runnable接口创建线程!");
    }
}
public class Thread\_2 {
    public static void main(String[] args) {
        //将实现Runnable接口的对象传入Thread构造方法中!
        Thread t1 = new Thread(new MyRun());
        t1.start();//创建线程
    }
}



我们来看看Thread类的4个构造方法!
在这里插入图片描述
Thread() 无参构造
通过继承Thread
Thread(Runnable target);
传入Runnable对象
Thread(String name);
给线程命名,便于程序员调试

在这里插入图片描述

  • 方法三
    Thread匿名内部类
public class Thread\_3 {
   public static void main(String[] args) {
       Thread t1 = new Thread(){
           @Override
           public void run() {
               System.out.println("Thread匿名内部类!");
           }
       };
       t1.start();
   }
}

在这里插入图片描述

  • 方法四
    Runnable接口匿名内部类
public class Thread\_5 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable匿名内部类!");
            }
        });
        t1.start();
    }
}

在这里插入图片描述

  • 方法五
    lambda表达式
    方法四/五的升级版!
public class Thread\_6 {
   public static void main(String[] args) {
       Thread t1 = new Thread(()->{
           System.out.println("lambda表达式!");
       });
       t1.start();
   }
}

在这里插入图片描述
我们比较推荐使用Runnable接口创建线程实例!
因为实现Runnable接口,可以让线程和线程执行的任务,更好进行解耦!!!
简单说就是Runnable方法创建线程实例, Runnable可以将线程和线程任务分开!
我们实现一个Runnable接口,我们只需要把入线程任务描述出来,不必关系那个线程执行该线程任务!,可能是线程,可能是进程,可能是协程,这些我们都不用关系!!!

Thread下的一些重要方法

start();

决定操作系统中是否真正创建了该线程!
如果没有执行该语句,那线程就不会执行!!!

run();

run只是一个方法,单纯描述了该线程,就是线程内容,并不是真正的run便没有创建好该线程!!!

中断线程

中断线程就是让线程停下来!

我们有两种方法中断线程,对应的关键就是让run方法执行完毕!!!
还有一个特殊的main线程,对于main线程就需要main方法执行完毕,线程才会结束!!!

  • 手动设置标志位

自己创建一个boolean变量, 来控制线程是否要执行结束!

public class Thread\_6 {
    public static void main(String[] args) {
        boolean isQuit =true; //其他线程控制该标志位!
        Thread t1 = new Thread(()->{
            while (true&&isQuit){
                System.out.println("Hello Thread!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
    }
}

我们其他的线程可以控制该标志位isQuit就可以中断该进程!!!

  • 使用Thread内置标志位,进行判定

Thread.interrupted(); 静态方法

在这里插入图片描述

Thread.currentThread();静态方法 返回当前线程实例!

在这里插入图片描述

interrupt(); 实例方法中断线程!

在这里插入图片描述

public class Thread\_7 {
    public static void main(String[] args) {
        Thread t1 = new Thread(()->{
            //
            while (Thread.currentThread().isInterrupted()){
                System.out.println("hello thread!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        t1.interrupt();
    }
}

当我们执行上面代码后:
在这里插入图片描述
代码打印了异常信息!
因为上方代码线程大部分时间是处于休眠状态阻塞!

而我们的interrupt();方法执行后,有两种情况!
1.该进程处于就绪状态,设置标志位为true
2.该进程处于休眠状态,抛出InterruptedException异常!

所以可以看到当执行完一次run便抛出异常,程序中断!我们在中断之前也把异常信息打印了!

线程等待join();

每个线程的调度顺序是无法确定的!如果我们要顺序执行某些线程就需要用到线程中的join方法

public class Thread\_9 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            while (true){
               //死循环 
            }
        });
        t1.start();
        t1.join(); // 让main线程等待t1线程执行完再执行!
        System.out.println("执行main线程");
    }
}

在这里插入图片描述
显然这个代码,我们无法等待t1线程执行结束!因为该线程是个死循环无法结束!

而这样的线程等待也毫无意义!毕竟一直死等下去,程序中断在此!

join(毫秒数);

我们的线程等待可以设置毫秒数,如果到了时间,那么其他线程也不会等待该线程,不管该线程是否结束!

//main线程等待t1线程10m后再执行
public class Thread\_9 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            while (true){
               //死循环
            }
        });
        t1.start();
        t1.join(10\_000); // 让main线程等待t1线程10m再执行!
                              //如果t1线程没有执行结束10m后过时不候!
        System.out.println("执行main线程");
    }
}

在这里插入图片描述

Thread.currentThread();静态方法 返回当前线程实例!

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYnVnIOmDrQ==,size_20,color_FFFFFF,t_70,g_se,x_16)

Thread.currentThread();静态方法 返回当前线程实例!

[外链图片转存中…(img-aWoZzB6Y-1715551142116)]
[外链图片转存中…(img-oGNPlejU-1715551142117)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值