多线程(二)——线程的状态和线程操作的相关方法

目录

    • 1、线程状态
    • 2、线程操作的相关方法

1、线程状态

线程状态:6种

线程状态(英文) 线程状态
NEW 新建状态
RUNNABLE 可运行状态(就绪状态)
TIMED_WAITING 睡眠状态
BLOCKED 阻塞状态
WAITING 等待状态
TERMINATED 终止状态(死亡状态)

线程的状态转换图:
多线程(二)——线程的状态和线程操作的相关方法_第1张图片
多线程(二)——线程的状态和线程操作的相关方法_第2张图片

2、线程操作的相关方法

方法名 作用
static native Thread currentThread() 返回当前线程
final synchronized void setName(String name) 设置线程名称
final void setPriority(int newPriority) 设置线程优先级
final void setDaemon(boolean on) 设置线程类型 ,加个参数true就是守护线程
final boolean isDaemon() 判断线程是不是守护线程
final String getName() 获取线程名称
long getId() 获取线程ID
final int getPriority() 获取线程优先级 Java线程优先级10个等级,最小的是1,默认值是5,最大的是10,优先级越高被优先调用的概率最高
final native boolean isAlive() 判断当前线程是否是存活状态,如果是返回true,否则返回false

重要方法:

方法 作用
void run() 线程的重要方法,实现线程的任务逻辑处理
synchronized void start() 启动线程一个Thread实例的start()方法只能被调用一次
static native void sleep(long millis) throws InterruptedException 休眠线程
final void join() throws InterruptedException 加入线程
static native void yield 线程礼让
void interrupt() 中断线程,抛出一个异常,使线程退出当前状态
boolean isInterrupted() 实例方法,用于判断当前线程是否已经被中断,是,返回true,否则返回false,线程中的中断状态不受该方法的影响
static boolean interrupted() 静态方法,用于判断执行中的线程是否已经被中断,若是,返回true,否则返回false,调用此方法后,线程的中断状态将被取消,即处于中断状态的线程将变为非中断状态

说明:

sleep():
静态方法,在主方法内,直接通过Thread.sleep()形式去调用sleep()方法,是休眠主线程。若想要线程实例休眠,sleep()方法应该放在run()方法内;sleep()方法指定的时间为线程不会运行的最短时间!

join():
a线程里面调用b线程这个方法后,a等待b执行完了或传递的参数时间到了才能继续执行;

yield():
暂停执行当前线程,并执行其他线程,就是让步一次执行时间片,使当前线程交出CPU的使用权(当前线程可能暂停),其他线程可被调度,可被调度的线程优先级要大于或等于当前线程,线程并不一定会停止执行,有可能再次获取CPU的使用权 (所以说这方法是不可靠的,得看系统心情)

interrupt():
如果线程因为I/O而停滞,进入非运行状态,基本上要等到I/O完成才能离开这个状态,在这种情况下,无法使用interrupt()方法来使这个程序离开run()方法;或者说interrupt()这个方法只对处于等待或者超时等待的线程有用,而对于处于正在运行的线程、阻塞的线程都是没有用的,

线程间通信方法
线程之间的通信方法是为了解决死锁问题的,
死锁:
使用synchronized同步方法或代码块时,假设线程A获得同步锁,在执行同步代码时,需要等待某资源,而该资源需要线程B提供,此时线程B无法获取线程A占用的同步锁,故而无法提供线程A需要的资源,因而导致死锁;

方法 作用
wait() 使当前线程等待,并让该线程释放对象锁,放进对象的等待池中,等待其他线程将其唤醒
notify() 通知方法,唤醒等待池中的线程,(随机选择一个唤醒)
notifyAll() 通知方法,唤醒等待池中所有线程

后台线程(守护线程):
线程分两种,用户线程(一般写的都是)和守护线程;如要将一个线程设置为后台线程,必须要在该线程启动前调用setDaemon()方法,设置后台线程后,可以通过isDaemon()方法判断该程序是否已经成为后台线程;

守护线程体是一个无限循环,如果所有的非守护线程都结束了,则守护线程自动终止;守护线程优先级一般较低;

线程的礼让:
可以用yield()方法来实现,该方法只能把运行权让出来,不能让给指定线程,即yield()方法让出运行权后,哪个线程抢占到,哪个线程就运行

sleep()和yield()都可以让出运行权,但他们还是有很大的不同

sleep() yield()
sleep()方法让出运行权时,不考虑其他线程的优先级 而yield()方法将运行权让给与其具有相同优先级或比其优先级更高的线程
调用sleep()方法会让当前线程转到阻塞状态 调用yield()方法则将将当前线程转到就绪状态
sleep()方法声明抛出InterruptedException异常 yield方法不抛出任何异常
sleep()方法比yield()方法具有更好的移植性,不能依靠yield()方法来提高程序的并发性

sleep()方法和wait()方法的异同
相同点:

  • 执行sleep()方法和wait()方法都会让出运行权,即CPU;
  • 执行sleep()方法和wait()方法都会让当前线程进入阻塞状态

不同点:

sleep() wait()
sleep()方法属于Thread类的静态方法 Object类的实例方法
定义sleep()方法时,必须设置休眠长度 wait()方法可以设定,也可以不设定
执行sleep()方法后可以使用interrupt()方法将休眠中的线程唤醒 执行wait()方法后可以使用notify()和notifyAll()唤醒等待线程
若线程T拥有对象o的对象锁,当sleep()方法后,线程T将进入对象o的锁池中,但是不会释放对象o的锁 执行wait()方法后,线程A将进入对象o的等待池,并释放o的锁,等待被唤醒后进入o的锁池,在等待获取对象o的锁和运行权
/**
 * @ClassName ThreadDaemonDemo
 * @Description 守护线程
 * @Author lzq
 * @Date 2018/12/13 19:29
 * @Version 1.0
 **/
class UserThread extends Thread {
    public void run() {
        System.out.println(this.getName()+"开始!");
        for(int i = 0;i < 5;i++) {
            System.out.println(this.getName()+" ||| "+(i+1));
            try {
                sleep(1000); //睡眠1秒,观察结果
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(this.getName()+"结束!");
    }
}

class DaemonThread extends Thread {
    public volatile boolean bExit = false;
    public void run() {
        System.out.println(this.getName()+"开始!");
        UserThread tu = new UserThread();
        tu.setName("用户线程2");
        tu.start();
        while (!bExit) {
            try {
                Thread.sleep(1000);  //睡眠1秒,观察结果
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(this.getName()+"结束!");
    }
}
public class ThreadDaemonDemo {
    public static void main(String[] args) {
        DaemonThread td = new DaemonThread();
        UserThread tu = new UserThread();
        td.setDaemon(true);
        td.setName("守护线程!");
        tu.setName("用户线程1");
        td.start();
        tu.start();
    }
}

多线程(二)——线程的状态和线程操作的相关方法_第3张图片
可以看出上例程序并没有打印出“守护线程结束!”,之所以会这样,是因为当程序中只有守护线程时,JVM是可以退出的,也就是说当程序中只有守护线程运行时,JVM会自动关闭;

所以非守护线程终止,即使存在守护线程,进程运行终止;

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