zoukankan      html  css  js  c++  java
  • Java Thread基础知识

    Java Thread基础知识

    java程序中只有一种途径去启动一个线程,即调用Thread类的start()方法。

    java中的线程状态

    在Thread类中有一个内部的枚举类State描述了线程的各个状态。

    public enum State {
            /**
             * 线程创建但未启动时会处于此状态
             */
            NEW,
    
            /**
             * 线程调用start方法,java虚拟机会启动一个线程,被认为是RUNNABLE状态,
             * 但此时可能在等待操作系统资源,比如等待cpu的处理器执行,
             * 所以可能并没有在操作系统中真正获取到处理器的执行权。
             */
            RUNNABLE,
    
            /**
             * 获取监视器失败后会处于此状态,比如调用了synchronized方法没有获取到锁时。
             */
            BLOCKED,
    
            /**
             * 线程在等待另一个线程执行特定操作时,会处于此状态,比如调用了Object.wait(),
             * 则会等待另一个线程调用Object.notify()或Object.notifyAll()方法。
             * 或者调用thread.join()等待被调用线程的执行结束。
             * 调用以下方法会使线程处于此状态
             *   		Object.wait() 
             *			Thread.join()
             *      LockSupport.park()
             * 注意:以上方法都是没有设置设置超时时间
             */
            WAITING,
    
            /**
             * 相较于WAITING状态,当设置了指定时间时,等待一定时间继续执行,线程处于此状态
             * 调用以下方法会使线程处于此状态
             *   		Object.wait( timeout ) 
    				 *   		Thread.sleep( timeout ) 
             *			Thread.join( timeout )
             *      LockSupport.parkNanos
             *			LockSupport.parkUntil
             */
            TIMED_WAITING,
    
            /**
             * 终止状态,线程执行完成。
             */
            TERMINATED;
        }
    

    线程常用方法

    start

    调用start()会开始执行一个线程,此时java虚拟机启动一个线程并调用该类的run()方法。

    sleep

    使当前线程休眠,放弃cpu使用权则或者放弃竞争cpu使用权,则放弃。

    注意:此时如果线程持有锁,不会释放。

    join

    此方法为线程的实例方法。A线程调用B线程的join方法,A线程将处于等待状态,直到B线程执行完后A线程才继续执行。

    interrupt

    中断线程。将线程从当前的一个状态中释放出来。当调用该方法时会将线程interrupt状态设置为true。比例调用了线程的 wait、join、sleep时,调用interrupt会中断线程的等待状态,继续执行,此时以上方法会抛出InterruptedException异常。或者线程阻塞于IO操作时,调用该方法会将线程中断,关闭IO操作流。

    Object的wait和notify

    wait

    此方法为Object的方法。调用此方法的前提为必须持有当前obj的锁,如果没有获取到锁而调用该方法会抛出java.lang.IllegalMonitorStateException。将当前运行的线程进入等待状态。并且释放obj的锁

    大多场景为当线程执行到特定逻辑时需要某些条件,当条件不满足时,调用wait方法进行等待。比如生产者/消费者模式,消费者需要等待生产者的数据准备好后才能执行。

    notify/notifyAll

    此方法为Object的方法。唤醒等待该obj的锁的线程,调用此方法的前提为必须持有当前obj的锁,如果没有获取到锁而调用该方法会抛出java.lang.IllegalMonitorStateException。此时被唤醒的线程需要重新获取该obj的锁才能运行。notify方法会从等待obj的多个线程中选择一个唤醒,notifyAll会唤醒所有的等待线程。

    Thread与Runnbale的关系

    开发线程类的两种方式

    • 继承Thread,重写run方法

      public class TestThread extends Thread {
      
          public static void main(String[] args) {
              new TestThread().start();
          }
      
          @Override
          public void run() {
              System.out.println("线程启动");
          }
      }
      
    • 实现Runnable接口,调用new Thread(target).start();

      public class TestRunnable implements Runnable {
          @Override
          public void run() {
              System.out.println("线程启动");
          }
      
          public static void main(String[] args) {
              TestRunnable target = new TestRunnable();
              new Thread(target).start();
          }
      }
      

    启动线程的方式

    上面代码是我们开发线程常用的两种方式,之所以说是开发不是启动,是因为java中启动线程只能通过Thread类的start方法。

    public class Thread implements Runnable {
      
      public synchronized void start() {
    
            if (threadStatus != 0)
                throw new IllegalThreadStateException();
    
            group.add(this);
    
            boolean started = false;
            try {
                start0();
                started = true;
            } finally {
                try {
                    if (!started) {
                        group.threadStartFailed(this);
                    }
                } catch (Throwable ignore) {
    
                }
            }
        }
      
      	private native void start0();
    }
    

    通过源码可以看到 start()调用了start0()方法,start0()是真正让java虚拟机去启动一个线程,此方法为虚拟机内部方法,虚拟机启动线程时会调用run()去执行具体的代码逻辑。所以结论为start方法为让虚拟机真正启动一个线程,而线程的执行逻辑则为run方法。

    如有不实,还望指正

  • 相关阅读:
    火炬之光使用了哪些技术
    计算机相关,性能开销,统计数据集锦
    IOS打开应用商店应用的几种方式
    IOS怎么获取plist文件里的属性
    IOS正则表达式的用法简介
    log4net学习
    技术之外
    百度面试题[转自CSDN]
    微软.NET开发认证基础技术知识大局观——核心篇
    基于ASP.NET 2.0 实现WEB打印方法的探讨
  • 原文地址:https://www.cnblogs.com/LuxBai/p/12638855.html
Copyright © 2011-2022 走看看