• 线程常见的几种方法


    线程中的静态方法

    1. sleep()方法:不释放锁

    概念:sleep会使当前线程睡眠指定时间(就是说当前线程暂停一段时间让给别的线程去运行,等到睡眠时间结束,线程自动复活),不释放锁

    关于释放锁 / 不释放锁
    sleep()是不释放锁的;也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象;因为当前线程仍然持有该对象的锁。

    用法

    public class ThreadTest extends Thread {
        @Override
        public void run() {
            System.out.println("我是重写后的run方法");
            try {
                sleep(2000);//ms单位
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("我是睡眠后被执行的");
        }
    
        public static void main(String[] args) {
            ThreadTest t1=new ThreadTest();
    //        ThreadTest t2=new ThreadTest();
            t1.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    线程状态:调用sleep方法使得线程从运行态—>阻塞态

    2. yield()方法:不释放锁

    概念: yield暂停当前正在执行的线程对象,让cpu去执行其他具有相同优先级的线程,不释放锁

    1.是让当前线程交出CPU权限,让CPU去执行其他具有相同优先级的的线程;
    2.使得线程回到就绪态,以允许具有相同优先级的其他线程获得运行机会。
    3.使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。

    总结: yield方法只能让拥有优先级的线程获取CPU执行时间的机会,调用该方法不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行的时间。
    线程状态:调用yield方法使得线程从运行态—>就绪态
    用法: 同上

    但是yield不能立刻交出CPU,会出现同一个线程一直执行的情况,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。

    举例:

    public class ThreadTest extends Thread {
        public void run() {
            System.out.println("In run");
            yield();
            System.out.println("Leaving run");
        }
        public static void main(String []argv) {
            (new ThreadTest()).start();
        }
    }
    //答案:程序运行可能输出先有In run后有Leaving run
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    线程中的实例方法

    1. start()方法

    我们去调用,想让线程去执行的方法

    线程创建以后,并不会自动运行,需要我们手动的调用start把线程的状置为为就绪状态;但不一定马上就被运行,得等到CPU分配时间片以后,才会运行。
    线程状态:调用start()方法,创建—>就绪

    2. run()方法

    cpu去调用,线程被真正 执行的方法

    线程真正要执行的逻辑,当一个线程被分配到cpu资源,开始启动就会调用run方法执行

    线程状态就绪—>运行

    3. join()方法:释放锁

    概念:join方法,当前线程调用某线程.join()时会使当前线程等待某线程执行完毕再结束,底层调用了wait,释放锁

    t1和t2两个线程,如果在t1线程里面调用了t2.join(),则t1线程会进行等待状态,t2运行结束以后,才会继续运行t1。这样可以保证线程的先后顺序。

    线程状态:调用join()方法,线程从运行态—>阻塞态

    4. wait()方法:释放锁 【wait notify notifyAll本质上是Object类的方法】

    注意:wait() 其实是Object类里面的方法,调用对象的wait方法导致线程放弃CPU的执行权,同时也放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool)

    概念wait()使当前线程阻塞,使当前线程回到线程池中等待,释放锁,当被其他线程使用notify,notifyAll 唤醒时进入就绪状态;(前提是必须先获得锁)

    一般配合synchronized来使用,即:在 synchronized 同步代码块里使用 wait()、notify() / notifyAll() 方法wait方法由当前所有的local对象里面调用,this.wait(),必须被try catch包围,保证即使异常中断也可以使wait等待的线程唤醒。执行了wait方法,需要被别的线程通过同一个对象的notify方法唤醒。

    线程状态:调用wait()方法,线程从运行态—>阻塞态
    总结wait notify notifyAll都必须在持有有锁的代码中

    5. notify() / notifyAll()方法:释放锁(不是立刻释放)

    概念

    • obj.notify:随机唤醒对象obj的某个wait线程,使被唤醒的线程进入就绪状态。

    • obj.notifyAll:唤醒对象obj的所有wait线程,使被唤醒的线程进入就绪状态。

    总结

    • notify/notifyAll()的执行只是唤醒沉睡的线程,而不会立即释放锁,锁的释放要看代码块的具体执行情况。
    • notify后不会立刻唤醒线程,而是等notify所在的synchronized(obj){}代码块执行完了,才会唤醒wait线程。
    • 在编程中,我们在使用notify/notifyAll() 后尽量迅速退出临界区,以唤醒其他线程让其获得锁。

    总结:

    1. sleep会使当前线程睡眠指定时间,不释放锁;
    2. join()底层就是调用wait()方法的,wait()释放锁资源,故join也释放锁资源
    3. yield会使当前线程重回到就绪状态,等待cpu的调度,不释放锁
    4. wait会使当前线程回到线程池中等待,释放锁,当被其他线程使用notify,notifyAll唤醒时进入可执行状态(就绪态)
    5. 当前线程调用 某线程 .join()时会使当前线程等待某线程执行完毕再结束,底层调用了wait,释放锁
  • 相关阅读:
    数据结构和算法(5):二叉树
    基于linux的web服务器(问题)
    Spring事务this自调用的理解误区?真的会让事务失效吗?
    李春葆、严蔚敏关于KMP算法的next数组值差1
    MySQL - 初识MySQL
    Mac 制作可引导安装器
    GDB使用技巧和相关插件
    【Redis入门笔记 08】主从复制 & 集群
    IT 安全方案,但是简易版
    大数据系统架构师的论文如何写
  • 原文地址:https://blog.csdn.net/m0_48904153/article/details/126488506