天天看点

多线程--03--Thread中的常用方法Thread中的常用方法线程的优先级线程的通信

Thread中的常用方法

概述

Thread类本质上是实现了Runnable接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过Thread类的start()实例方法。Start()方法是一个native方法,它将通知底层操作系统,最终由操作系统启动一个新线程,操作系统将执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。

Thread中的常用方法

  1. start():启动当前线程;调用当前线程的run()
  2. run(): 通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
  3. currentThread():静态方法,返回执行当前代码的线程
  4. getName():获取当前线程的名字
  5. setName():设置当前线程的名字
  6. yield():释放当前cpu的执行权
  7. join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才 结束阻塞状态。
  8. stop():已过时。当执行此方法时,强制结束当前线程。
  9. sleep(long millitime):让当前线程“睡眠”指定的millitime毫秒。在指定的millitime毫秒时间内,当前线程是阻塞状态。
  10. isAlive():判断当前线程是否存活
多线程--03--Thread中的常用方法Thread中的常用方法线程的优先级线程的通信
多线程--03--Thread中的常用方法Thread中的常用方法线程的优先级线程的通信

线程阻塞api:

  • sleep()方法:

    该方法允许指定以ms为单位的一段时间作为参数, 它使得线程在指定的时间内进入阻塞状态,不能得到CPU时间,

    指定时间已过,线程重新进入可执行状态.

  • suspend()和resume()方法:

    配套使用, suspend()使得线程进入阻塞状态,且不会自动恢复,必须将其对应的resume()调用, 才可以使线程进入可执行状态.

  • yield():

    使得线程放弃当前分得的CPU时间, 但是不使线程阻塞, 即线程仍然处于可执行状态;

  • wait()和notify()方法:

    配套使用,若wait()有参数,相当于sleep(但可以通过notify强行唤醒), wait()没有参数,相当于suspend(), 需要通过notify唤醒

sleep(0)和sleep(1)和不要sleep的区别:

sleep(0)

  • 如果线程调度器的可运行队列中有大于或等于当前线程优先级的就绪线程存在,操作系统会将当前线程从处理器上移除,调度其他优先级高的就绪线程运行;如果可运行队列中的没有就绪线程或所有就绪线程的优先级均低于当前线程优先级,那么当前线程会继续执行,就像没有调用Sleep(0)一样。

Sleep(1)

  • 会引发线程上下文切换:调用线程会从线程调度器的可运行队列中被移除一段时间,这个时间段约等于 timeout 所指定的时间

线程的优先级

线程的调度

多线程--03--Thread中的常用方法Thread中的常用方法线程的优先级线程的通信

优先级

多线程--03--Thread中的常用方法Thread中的常用方法线程的优先级线程的通信
多线程--03--Thread中的常用方法Thread中的常用方法线程的优先级线程的通信

线程的通信

案例

多线程--03--Thread中的常用方法Thread中的常用方法线程的优先级线程的通信

实现:

class Number implements Runnable{
    private int number = 1;
    private Object obj = new Object();
    @Override
    public void run() {

        while(true){

            synchronized (obj) {

                obj.notify();

                if(number <= 100){

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;

                    try {
                        //使得调用如下wait()方法的线程进入阻塞状态
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }else{
                    break;
                }
            }

        }

    }
}


public class CommunicationTest {
    public static void main(String[] args) {
        Number number = new Number();
        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);

        t1.setName("线程1");
        t2.setName("线程2");

        t1.start();
        t2.start();
    }
}
           

涉及到的三个方法:

  • wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
  • notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的那个。
  • notifyAll():一旦执行此方法,就会唤醒所有被wait的线程。
多线程--03--Thread中的常用方法Thread中的常用方法线程的优先级线程的通信

说明:

1.wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中。

2.wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器。 否则,会出现IllegalMonitorStateException异常

3.wait(),notify(),notifyAll()三个方法是定义在java.lang.Object类中。

多线程--03--Thread中的常用方法Thread中的常用方法线程的优先级线程的通信

面试题:sleep() 和 wait()的异同?

1.相同点:

一旦执行方法,都可以使得当前的线程进入阻塞状态。

2.不同点:

1)两个方法声明的位置不同:Thread类中声明sleep() , Object类中声明wait()

2)调用的要求不同:sleep()可以在任何需要的场景下调用。 wait()必须使用在同步代码块或同步方法中

3)关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁。

继续阅读