• Thread类的基本用法


    1.线程创建

    1.继承Thread类,重写run()方法

    1. class MyThread extends Thread{
    2. @Override
    3. public void run() {
    4. System.out.println("hello thread");
    5. }
    6. }
    7. public class Demo1 {
    8. public static void main(String[] args) {
    9. MyThread t=new MyThread();//把线程和线程要完成的任务耦合在一起
    10. t.start();//另外启动新线程,执行run中的逻辑,是一个单独执行流,和现有执行流不相关。并发执行
    11. System.out.println("hello main");
    12. }
    13. }

    2.实现Runnable接口,重写run()方法

    1. class MyRunnable implements Runnable{
    2. @Override
    3. public void run() {
    4. while (true) {
    5. System.out.println("hello MyRunnable");
    6. try {
    7. Thread.sleep(1000);
    8. } catch (InterruptedException e) {
    9. throw new RuntimeException(e);
    10. }
    11. }
    12. }
    13. }
    14. public class Demo2 {
    15. public static void main(String[] args) {
    16. MyRunnable myRunnable=new MyRunnable();
    17. Thread t=new Thread(myRunnable);//把线程要干的事和线程分开,使用Runnable专门表示线程要完成的工作
    18. t.start();
    19. while (true){
    20. System.out.println("hello main");
    21. try {
    22. Thread.sleep(1000);
    23. } catch (InterruptedException e) {
    24. throw new RuntimeException(e);
    25. }
    26. }
    27. }
    28. }

    3.继承Thread类,使用匿名内部类

    1. public class Demo3 {
    2. /**
    3. *使用匿名内部类,创建thread子类同时实例化出一个thread对象
    4. * @param args
    5. */
    6. public static void main(String[] args) {
    7. Thread t=new Thread(){
    8. @Override
    9. public void run() {
    10. while(true){
    11. System.out.println("hello thread");
    12. try {
    13. Thread.sleep(1000);
    14. } catch (InterruptedException e) {
    15. throw new RuntimeException(e);
    16. }
    17. }
    18. }
    19. };
    20. t.start();
    21. while(true){
    22. System.out.println("hello main");
    23. try {
    24. Thread.sleep(1000);
    25. } catch (InterruptedException e) {
    26. throw new RuntimeException(e);
    27. }
    28. }
    29. }
    30. }

    4.实现Runnable接口,使用匿名内部类

    1. public class Demo4 {
    2. /**
    3. * 使用匿名内部类 实现Runnable接口
    4. * @param args
    5. */
    6. public static void main(String[] args) {
    7. Thread t=new Thread(new Runnable() {
    8. @Override
    9. public void run() {
    10. while(true){
    11. System.out.println("hello thread");
    12. try {
    13. Thread.sleep(1000);
    14. } catch (InterruptedException e) {
    15. throw new RuntimeException(e);
    16. }
    17. }
    18. }
    19. });
    20. t.start();
    21. while(true){
    22. System.out.println("hello main");
    23. try {
    24. Thread.sleep(1000);
    25. } catch (InterruptedException e) {
    26. throw new RuntimeException(e);
    27. }
    28. }
    29. }
    30. }

    5.使用lambda表达式(推荐)

    1. public class Demo5 {
    2. /**
    3. * lambda表达式,推荐写法
    4. * @param args
    5. */
    6. public static void main(String[] args) {
    7. Thread t=new Thread(()->{
    8. while (true){
    9. System.out.println("hello thread");
    10. try {
    11. Thread.sleep(1000);
    12. } catch (InterruptedException e) {
    13. throw new RuntimeException(e);
    14. }
    15. }
    16. });
    17. t.start();
    18. while(true){
    19. System.out.println("hello main");
    20. try {
    21. Thread.sleep(1000);
    22. } catch (InterruptedException e) {
    23. throw new RuntimeException(e);
    24. }
    25. }
    26. }
    27. }

    2.启动线程(start和run的区别)

    1. class MyThread extends Thread{
    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. throw new RuntimeException(e);
    10. }
    11. }
    12. }
    13. }
    14. public class Demo1 {
    15. public static void main(String[] args) {
    16. MyThread t=new MyThread();
    17. //t.run();直接调用run
    18. t.start();
    19. while (true){
    20. System.out.println("hello main");
    21. try {
    22. Thread.sleep(1000);
    23. } catch (InterruptedException e) {
    24. throw new RuntimeException(e);
    25. }
    26. }
    27. }
    28. }

     第一个截图是调用start,是创建线程,在新线程里面执行代码,和main线程并发执行。

    第二个截图是调用run,没有创建线程,而是在原来的main线程执行代码

    线程中断

    本质是让run方法快点结束,而不是让run执行一般中止。

    方法1:自己定义一个标志位,作为线程是否结束的标志

    1. public class Demo9 {
    2. public static boolean isQuit=false;//自定义一个标志
    3. public static void main(String[] args) {
    4. Thread t=new Thread(()->{
    5. while (!isQuit) {
    6. System.out.println("hello thread");
    7. try {
    8. Thread.sleep(1000);
    9. } catch (InterruptedException e) {
    10. throw new RuntimeException(e);
    11. }
    12. }
    13. });
    14. t.start();
    15. try {
    16. Thread.sleep(3000);
    17. } catch (InterruptedException e) {
    18. throw new RuntimeException(e);
    19. }
    20. isQuit=true;//3秒后线程结束
    21. }
    22. }

    方法2:使用标准库自带的标记

    1. public class Demo10 {
    2. public static void main(String[] args) {
    3. Thread t = new Thread(() -> {
    4. while (!Thread.currentThread().isInterrupted()) {
    5. //currentThread()是一个静态方法,通过它可以获得当前线程对应的Thread对象
    6. //isInterrupted()用于判定标志位
    7. System.out.println("hello thread");
    8. try {
    9. Thread.sleep(1000);
    10. } catch (InterruptedException e) {
    11. //throw new RuntimeException(e);
    12. //1.立即结束线程
    13. //break;
    14. //2.不做处理
    15. //3.稍后处理
    16. try {
    17. Thread.sleep(1000);
    18. } catch (InterruptedException ex) {
    19. throw new RuntimeException(ex);
    20. }
    21. break;
    22. }
    23. }
    24. });
    25. t.start();
    26. try {
    27. Thread.sleep(3000);
    28. } catch (InterruptedException e) {
    29. throw new RuntimeException(e);
    30. }
    31. t.interrupt();//通过他中断线程,设置标志位为true
    32. /*
    33. interrupt方法有两种情况
    34. 1.t线程在运行时,会设置标志位为true
    35. 2.t线程在阻塞状态(sleep),不会设置标志位,而是触发InterruptedException,这个异常会把sleep提前唤醒.
    36. 所以处理异常时直接break;
    37. */
    38. }
    39. }

    线程等待

    线程之间的调度是不确定的,可以通过join()方法控制线程的结束顺序

    1. public class Demo11 {
    2. public static void main(String[] args) {
    3. Thread t=new Thread(()->{
    4. for (int i = 0; i < 5; i++) {
    5. System.out.println("hello thread");
    6. try {
    7. Thread.sleep(1000);
    8. } catch (InterruptedException e) {
    9. throw new RuntimeException(e);
    10. }
    11. }
    12. });
    13. t.start();
    14. try {
    15. t.join();//main线程进入阻塞,t线程继续参与调度
    16. } catch (InterruptedException e) {
    17. throw new RuntimeException(e);
    18. }
    19. System.out.println("hello main");
    20. }
    21. }

    如果调用join方法之前,t线程已经结束,此时join不需要阻塞等待。

    线程休眠sleep() 

    操作系统管理线程PCB的时候,是有多了链表的。其中有阻塞队列,就绪队列,调用sleep()时PCB会从 就绪队列移动 到 阻塞队列。只有就绪队列才会参与cpu调度,当sleep时间到了就会从新回到就绪队列(不代表立即在cpu上执行)

  • 相关阅读:
    简单讲解ANSI Unicode、GBK、GB2312
    进程间的通信
    【笔试刷题训练】day_05
    BigDecimal 用法总结
    计算机毕业设计 SSM学校图书借阅管理系统 图书馆借阅管理系统 图书借阅系统Java
    最新科目一攻略(新规)
    10 个关于 Promise 和 setTimeout 知识的面试题,通过图解一次说透彻
    实用网站合集
    关于logback的一个坑:日志级别设置无效
    巨控GRM230模块在分散式污水行业专用解决方案
  • 原文地址:https://blog.csdn.net/weixin_61427900/article/details/126599439