多线程基础学习一:Thread基础学习

r囧r小猫 2022-06-09 08:09 305阅读 0赞

最近开始学习多线程的基础知识,以学习使用为主。

创建一个线程

Thread是一个实现了Runnable接口的实现类,所以创建线程只要集成重写run方法就可以了。

  1. /** * Created by nyl * 2017/9/15 0015 */
  2. public class DaemonTest {
  3. public static void main (String[] args) {
  4. Thread thread = new MyThread();
  5. //thread.setDaemon(true);
  6. thread.start();
  7. System.out.println("main主线程结束");
  8. }
  9. private static class MyThread extends Thread{
  10. @Override
  11. public void run () {
  12. int i = 0;
  13. while(i <= 10) {
  14. try {
  15. Thread.sleep(1000);
  16. i++;
  17. System.out.println("执行第" + i + "次");
  18. } catch (InterruptedException e) {
  19. e.printStackTrace();
  20. } finally {
  21. System.out.println("我出现异常了");
  22. }
  23. }
  24. }
  25. }
  26. }

启动线程的方法是start方法,看到网上经常有人问run() 和start()方法区别,自己也尝试了一下,其实run方法,只是实例化了一个对象,调用了对象的一个方法,没有创建新线程,start方法则创建了新线程。
调用start方法执行结果:

  1. main主线程结束
  2. 执行第1
  3. 执行第2
  4. 执行第3
  5. 执行第4
  6. 执行第5
  7. 执行第6
  8. 执行第7
  9. 执行第8
  10. 执行第9
  11. 执行第10
  12. 执行第11

可以看到一开始就是main主线程结束了,然后才是新线程执行的结果,如果调用run方法,结果如下:

  1. 执行第2
  2. 执行第3
  3. 执行第4
  4. 执行第5
  5. 执行第6
  6. 执行第7
  7. 执行第8
  8. 执行第9
  9. 执行第10
  10. 执行第11
  11. 执行第12
  12. main主线程结束

可以看到,先把run方法执行完,才输出了main线程结束,其实run方法和普通方法调用一样,调用一次执行一次。

网上看到关于守护线程daemon的内容,如果java虚拟机没有非守护线程,就会退出,测试了一下:
设置(默认false)

  1. thread.setDaemon(true);

执行结果

  1. main主线程结束

结果只输出了这一句话,看来线程还没执行虚拟机就退出了。但是我注意到,并没有输出“我出现异常了”这句话,一般finally都会执行,看来这种情况finally不执行了。

常用方法

  • 等待一段时间继续执行
    sleep(毫秒数),这个方法是Thread的类方法,它的注释是这么写的:

    如果任何线程中断了当前线程。当抛出此异常时,当前线程的中断状态被清除。

首先,sleep方法并没释放锁,当前线程会休眠指定的时间,调用方式一般是这样的:

  1. Thread.sleep(1000);

在哪个线程里写,哪个线程就会休眠执行指定时间。还有另外一种写法,是这样的:

  1. Thread.currentThread().sleep(1000);

个人觉得多此一举,完全没有必要这么写。

还有一些有特殊意义的写法,比如sleep(0) ,sleep(1),目前还不清楚它们的意义。
测试代码:

  1. /** * Created by nyl * 2017/9/15 0015 */
  2. public class DaemonTest {
  3. public static void main (String[] args) {
  4. Thread thread = new MyThread();
  5. //thread.setDaemon(true);
  6. thread.start();
  7. System.out.println("main主线程结束");
  8. try {
  9. //thread.stop();
  10. Thread.sleep(5000);
  11. System.out.println("等待5s结束");
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. }
  16. private static class MyThread extends Thread{
  17. @Override
  18. public void run () {
  19. int i = 0;
  20. while(i <= 10) {
  21. try {
  22. Thread.sleep(1000);
  23. i++;
  24. System.out.println("执行第" + (i + 1) + "次");
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. } finally {
  28. //System.out.println("我出现异常了");
  29. }
  30. }
  31. }
  32. }
  33. }

输出结果:

  1. 执行第2
  2. 执行第3
  3. 执行第4
  4. 执行第5
  5. 执行第6
  6. 等待5s结束
  7. 执行第7
  8. 执行第8
  9. 执行第9
  10. 执行第10
  11. 执行第11
  12. 执行第12

可以看到,主线程等待了5秒,新线程没有受影响。

  • 暂停与恢复
    suspend() 是暂停方法, resume()是恢复方法,两个都是对象方法,测试代码如下:

    public class PasueTest {

    1. public static void main (String[] args) {
    2. Thread thread = new MyThread();
    3. thread.start();
    4. System.out.println("main主线程结束");
    5. try {
    6. thread.suspend();
    7. Thread.sleep(5000);
    8. System.out.println("等待5s结束");
    9. System.out.println("暂停执行5s");
    10. thread.resume();
    11. System.out.println("恢复重新执行");
    12. } catch (InterruptedException e) {
    13. e.printStackTrace();
    14. }
    15. }
    16. private static class MyThread extends Thread{
    17. @Override
    18. public void run () {
    19. System.out.println("我执行了");
    20. }
    21. }

    }

执行出现了两中结果,第一种:

  1. main主线程结束
  2. 等待5s结束
  3. 暂停执行5s
  4. 恢复重新执行
  5. 我执行了

第二种:

  1. main主线程结束

一直卡在那了
不知道第二种情况为什么会出现,总而言之这两个方法已经过时了,还有其它方面的问题,不要再用了。

  • 终结线程

终止线程有五个方法,分别为stop()、cancle() (Runnable)、 interrupt()(抛出异常或者自己处理)以及标志位结束,其中stop方法已经过期,这个方法不会释放资源。

cancle方法的使用:

  1. public class CancleTest {
  2. public static void main (String[] args) {
  3. Thread first = new Thread(new CancleThread());
  4. first.setDaemon(true);
  5. first.start();
  6. SleepUtil.sleep(5000);
  7. System.out.println("线程取消了");
  8. }
  9. static class CancleThread implements Runnable {
  10. @Override
  11. public void run () {
  12. while (true) {
  13. SleepUtil.sleep(1000);
  14. System.out.println("我执行了");
  15. }
  16. }
  17. }
  18. }

执行结果:

  1. 我执行了
  2. 我执行了
  3. 我执行了
  4. 我执行了
  5. 我执行了
  6. 线程取消了

interrupt()(抛出异常或者自己处理):

  1. public class InterruptedTest {
  2. public static void main (String[] args) {
  3. Thread first = new InterruptedThread();
  4. first.setDaemon(true);
  5. Thread second = new Interrupted1Thread();
  6. second.setDaemon(true);
  7. first.start();
  8. second.start();
  9. try {
  10. Thread.sleep(5000);
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. first.interrupt();
  15. System.out.println("first interrupt is " + first.isInterrupted());
  16. SleepUtil.sleep(50);
  17. }
  18. static class InterruptedThread extends Thread {
  19. @Override
  20. public void run () {
  21. while (true) {
  22. try {
  23. Thread.sleep(1000);
  24. System.out.println("中断状态是:" + Thread.interrupted());
  25. } catch (Exception e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }
  30. }
  31. }

执行结果:

  1. 中断状态是:false
  2. 中断状态是:false
  3. 中断状态是:false
  4. 中断状态是:false
  5. java.lang.InterruptedException: sleep interrupted
  6. at java.lang.Thread.sleep(Native Method) at learn.threadlearn.InterruptedTest$InterruptedThread.run(InterruptedTest.java:40) 中断状态是:false first interrupt is true

抛出了InterruptedException异常(finally会被执行),这个异常抛出时,会清除中断状态.

标志位结束:

  1. public class FlagTest {
  2. private static boolean type = true; // 标志位, 这样写不严谨,有风险
  3. public static void main (String[] args) {
  4. FlagThread first = new FlagThread();
  5. first.setDaemon(true);
  6. first.start();
  7. SleepUtil.sleep(5000);
  8. type = false;
  9. SleepUtil.sleep(2000);
  10. }
  11. static class FlagThread extends Thread {
  12. @Override
  13. public void run () {
  14. while (type) {
  15. SleepUtil.sleep(1000);
  16. System.out.println("正在执行");
  17. }
  18. System.out.println("执行结束了");
  19. }
  20. }
  21. }

执行结束:

  1. 正在执行
  2. 正在执行
  3. 正在执行
  4. 正在执行
  5. 正在执行
  6. 执行结束了

以上集中方式都可以结束线程。

发表评论

表情:
评论列表 (有 0 条评论,305人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java 线基础学习

    一、线程概念  1、进程:程序运行资源分配的最小单位,每个进程都有自己独立的代码和数据空间,操作系统为进程分配各种资源。  2、线程:CPU调度的最小单位,也叫轻量级进程,