java线程

Java线程

    • java线程的状态类别介绍
    • java线程基本操作
      • 新建线程、启动线程、终止线程
      • 线程中断
      • 等待wait和通知notify
      • 挂起suspend和继续执行resume
      • 等待线程结束join和谦让yield

java线程的状态类别介绍

java中一个线程总共有6种状态,都在Thread类中的State枚举中定义:

	public enum State {
	    NEW,
	    RUNNABLE,
	    BLOCKED,
	    WAITING,
	    TIMED_WAITING,
	    TERMINATED;
	}
  1. NEW:尚未启动的线程状态;还没有使用Thread.start()方法进行线程启动;

  2. RUNNABLE:该线程处于一个可运行的状态,使用了Thread.start()方法进行线程启动;但也有可能该线程正在等待操作系统为它分配执行时间;

  3. BLOCKED:该线程处于一个阻塞的状态,比如线程运行遇到了一个同步代码块,则会进入阻塞状态直到获取到一个排它锁资源;

  4. WAITING:该线程处于一个无时间限制的等待状态(处于这种状态的线程不会被分配处理器执行时间):没有设置Timeout参数的Object::wait()方法;没有设置Timeout参数的Thread::join()方法;LockSupport::park()方法。

  5. TIMED_WAITING:该线程处于一个有时间限制的等待状态(处于这种状态的线程不会被分配处理器执行时间):不过无须等待 被其他线程显式唤醒,在一定时间之后它们会由系统自动唤醒。
    以下方法会让线程进入限期等待状态:
    Thread::sleep()方法;
    设置了Timeout参数的Object::wait()方法;
    设置了Timeout参数的Thread::join()方法;
    LockSupport::parkNanos()方法;
    LockSupport::parkUntil()方法。

  6. TERMINATED:线程已终止的状态,线程已经结束执行。

  7. WAITING和BLOCKED的区别:“等待状态”与“阻塞状态”的区别是“阻塞状态”在等待着获取到一个排它锁进入同步代码块,这个事件将在另外一个线程放弃这个锁的时候发生;而“等待状态”则是在等待一段时间,或者唤醒动作的发生。
    java线程_第1张图片

java线程基本操作

新建线程、启动线程、终止线程

  1. 最简单的两种新建线程方式:继承Thread类、实现Runnable接口。由于java是单继承的,也就是说继承本身是一种很宝贵的资源,因此我们在上述两种方式中更偏向选择实现Runnable类来创建一个线程。直接使用Thread t1 = new Thread(runnable)并进行t1.start()方法的调用,那么java虚拟机就会新建一个线程并执行runnable实例中重新的run方法;
  2. 线程Thread有一个run()方法,t1.start()线程启动后就会执行run方法,而如果直接使用t1.run()是不会创建一个线程的,而是在当前线程中串行调用run()方法,只是作为一个普通的方法调用。
  3. Thread类提供了一个stop()方法进行线程终止,但是该方法已经被标注为一个废弃的方法。原因是该方法停止线程的方式过于暴力,直接无视任何情况,直接停止该线程。假如线程正在给某一个对象的部分字段进行赋值,然后突然被强制停止关闭了该线程,那么该对象的数据就是不完整的。

线程中断

  1. 中断线程,设置中断状态标志:public void Thread interrupt();
  2. 判断线程是否被中断:public boolean Thread isInterrupted();
  3. 判断线程是否被中断,并清除中断状态标志:public static boolean Thread interrupted():
  4. interrup()方法只是设置了中断状态标志,具体的线程中断退出操作需要在线程中进行逻辑代码处理。比如使用Thread.currentThread.isInterrupted()方法就可以知道当前线程的中断状态标志,再根据实际情况进行中断操作处理即可;
  5. InterruptedException是一个中断异常,它不是运行时异常,也就是说程序必须捕获并进行处理。当线程在sleep()或者wait()时,如果被中断,这个异常就会发生。
    public static native void sleep(long millis) throws InterruptedException;

    public final native void wait(long timeout) throws InterruptedException;

假如在InterruptedException的异常捕获catch操作中,只是做了对资源进行释放的操作,那么建议最后重新设置中断状态Thread.currentThread.interrupted();以便让中断检查代码正确执行。

等待wait和通知notify

  1. wait和notify是jdk提供的两个多线程之间通信协作的方法;这两个方法属于Object类。
  2. 当在一个对象实例上调用了wait()方法后,obj.wait(),当前线程就会进入obj对象的等待队列,并转为等待状态。直到其他线程调用了obj.notify()方法为止。当notify()被调用时,它就会从这个等待队列中,随机选择一个线程,并将其唤醒。这个选择时不公平的,随机的。notifyAll()方法时唤醒等待队列中所有等待的线程,而不是随机选择一个。
  3. wait()和notify()方法的调用必须包含在对应的synchronizied语句中,都需要首先获得目标对象的一个监视器(monitor)。
  4. wait()方法会释放目标对象的锁,而THread.sleep()方法不会释放任何资源。

挂起suspend和继续执行resume

  1. 这两个操作时一对相反的操作,被suspend挂起的线程必须要等到resume才能继续执行;但是suspend挂起的线程期间并不会释放任何锁资源。
  2. 这两个方法已被标注为废弃方法。因为假如resume操作意外地在suspend前就执行了,那么被挂起的线程就难有机会继续执行了。并且,它所占用的锁也不会被释放,严重的话甚至影响整个系统正常工作。

等待线程结束join和谦让yield

  1. join()的本质是让调用线程wait()在当前线程对象实例上。下述代码中,调用线程就是main线程,线程对象实例就是at线程。所以main线程会在at线程对象实例上等待wait。直到at线程执行完毕后,就会在退出前调用notifyAll()通知所有的等待线程继续执行。main线程才会打印“main Thread end!”语句。
public static void main(String[] args) throw InterruptedException{
    AddThread at = new AddThread();
    at.start();
    at.join();
    System.out.println("main Thread end!");
}
  1. 第一个join()方法表示无限等待,他会一直阻塞调用线程,知道目标线程执行完毕。第二个方法给出了一个最大等待时间。
public final void join() throws InterruptedException

public final synchronized void join(long millis) throws InterruptedException
  1. yield()是Thread类的一个静态方法,他会使当前线程让出cpu,但是当前线程让出cpu后仍会进行cpu资源的争夺。
public static native void yield();

你可能感兴趣的:(java线程)