java面试-多线程&并发篇2-线程通知、等待、中断,同步锁,同步执行(7-11,共29)

2022-09-23 19:07:5308:27 366
所属专辑:Java面试系列
声音简介

你好,今天我要和您分享的是java面试--多线程和并发篇(7-11个小节,共29个小节),


在上期当中,我们学习了:


Java中实现多线程有几种方法,

如何停止一个正在运行的线程,

notify()和notifyAll()有什么区别,

sleep()和wait() 有什么区别,

volatile 是什么?可以保证有序性吗,

Thread 类中的start() 和 run() 方法有什么区别



今天我们来学习:


为什么wait, notify 和 notifyAll这些方法不在thread类里面?

为什么wait和notify方法要在同步块中调用?

Java中interrupted 和 isInterrupted方法的区别

Java中synchronized 和 ReentrantLock 有什么不同?

有三个线程T1,T2,T3,如何保证顺序执行?



那话不多说,我们开始学习吧



7、为什么wait, notify 和 notifyAll这些方法不在thread类里面?


明显的原因是JAVA提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得。如果线程需要等待某些锁那么调用对象中的wait()方法就有意义了。如果wait()方法定义在Thread类中,线程正在等待的是哪个锁就不明显了。简单的说,由于wait,notify和notifyAll都是锁级别的操作,所以把他们定义在Object类中因为锁属于对象。


8、为什么wait和notify方法要在同步块中调用?


只有在调用线程拥有某个对象的独占锁时,才能够调用该对象的wait(),notify()和notifyAll()方法。

如果你不这么做,你的代码会抛出IllegalMonitorStateException异常。

还有一个原因是为了避免wait和notify之间产生竞态条件。


wait()方法强制当前线程释放对象锁。这意味着在调用某对象的wait()方法之前,当前线程必须已经获得该对象的锁。因此,线程必须在某个对象的同步方法或同步代码块中才能调用该对象的wait()方法。


在调用对象的notify()和notifyAll()方法之前,调用线程必须已经得到该对象的锁。因此,必须在某个对象的同步方法或同步代码块中才能调用该对象的notify()或notifyAll()方法。


调用wait()方法的原因通常是,调用线程希望某个特殊的状态(或变量)被设置之后再继续执行。调用notify()或notifyAll()方法的原因通常是,调用线程希望告诉其他等待中的线程:"特殊状态已经被设置"。这个状态作为线程间通信的通道,它必须是一个可变的共享状态(或变量)。



9、Java中interrupted 和 isInterrupted方法的区别?


interrupted() 和 isInterrupted()的主要区别是前者会将中断状态清除而后者不会。Java多线程的中断机制是用内部标识来实现的,调用Thread.interrupt()来中断一个线程就会设置中断标识为true。当中断线程调用静态方法Thread.interrupted()来检查中断状态时,中断状态会被清零。而非静态方法isInterrupted()用来查询其它线程的中断状态且不会改变中断状态标识。简单的说就是任何抛出InterruptedException异常的方法都会将中断状态清零。无论如何,一个线程的中断状态有有可能被其它线程调用中断来改变。


10、Java中synchronized 和 ReentrantLock 有什么不同?


相似点:

这两种同步方式有很多相似之处,它们都是加锁方式同步,而且都是阻塞式的同步,也就是说当如果一个线程获得了对象锁,进入了同步块,其他访问该同步块的线程都必须阻塞在同步块外面等待,而进行线程阻塞和唤醒的代价是比较高的.


区别:

这两种方式最大区别就是对于Synchronized来说,它是java语言的关键字,是原生语法层面的互斥,需要jvm实现。而ReentrantLock它是JDK 1.5之后提供的API层面的互斥锁,需要lock()和unlock()方法配合try/finally语句块来完成。

Synchronized经过编译,会在同步块的前后分别形成monitorenter和monitorexit这个两个字节码指令。在执行monitorenter指令时,首先要尝试获取对象锁。如果这个对象没被锁定,或者当前线程已经拥有了那个对象锁,把锁的计算器加1,相应的,在执行monitorexit指令时会将锁计算器就减1,当计算器为0时,锁就被释放了。如果获取对象锁失败,那当前线程就要阻塞,直到对象锁被另一个线程释放为止。

由于ReentrantLock是java.util.concurrent包下提供的一套互斥锁,相比Synchronized,ReentrantLock类提供了一些高级功能,主要有以下3项:


1、等待可中断,持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待,这相当于Synchronized来说可以避免出现死锁的情况。


2、公平锁,多个线程等待同一个锁时,必须按照申请锁的时间顺序获得锁,Synchronized锁非公平锁,ReentrantLock默认的构造函数是创建的非公平锁,可以通过参数true设为公平锁,但公平锁表现的性能不是很好。


3、锁绑定多个条件,一个ReentrantLock对象可以同时绑定多个对象。


11、有三个线程T1,T2,T3,如何保证顺序执行?


在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。


实际上先启动三个线程中哪一个都行, 因为在每个线程的run方法中用join方法限定了三个线程的执行顺序。


public class JoinTest2

// 1.现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行
    public static void main(String[] args) {
        final Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t1");
            }
        });
        final Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 引用t1线程,等待t1线程执行完
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t2");
            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 引用t2线程,等待t2线程执行完
                    t2.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t3");
            }
        });
        t3.start();//这里三个线程的启动顺序可以任意,大家可以试下!
        t2.start();
        t1.start();
    }

 }



好了,今天我们学习了:

为什么wait, notify 和 notifyAll这些方法不在thread类里面?

为什么wait和notify方法要在同步块中调用?

Java中interrupted 和 isInterruptedd方法的区别

Java中synchronized 和 ReentrantLock 有什么不同?

有三个线程T1,T2,T3,如何保证顺序执行?



希望对你所帮助,我们下期再见


坚持学习,加油


用户评论

表情0/300
喵,没有找到相关结果~
暂时没有评论,下载喜马拉雅与主播互动
猜你喜欢
【下载器】Java多线程项目实战-熟练应用多线程技术

资料获取方式:+v号java1060视频资料获取方式在专辑第一条视频下方评论区处!!!对于学习完JavaSE特别是多线程技术后想捣鼓点自己的东西,想找个项目实战...

by:动力节点教育

Java多线程高并发编程马士兵老师

全部视频源码笔记在微信公众号:程序员理想,全套资料视频或更多大数据,java,java架构师,区块链,等等资料也在微信公众号:程序员理想

by:优效学院Java架构嘿

【完整版】动力节点Java多线程实战教程全集

资料获取方式:+v号java1060线程是进程中的一个独立控制单元,线程在控制着进程的执行,一个进程中至少有一个线程。多线程可以更好地利用cpu的资源,线程之间...

by:动力节点教育

java面试

高质量面试题逐字逐句整理,若需要音频同步资料,请扫专辑二维码进群领取

by:昔玛蜡瓦

Java面试

2024年的java面试知识总结,内容包含了Java基础、集合类、Java并发、JVM、Spring、SpringCloud、MySQL、Mybatis、Tom...

by:小爱和云天

JAVA面试题

java码农基础面试题,搞定面试

by:摔了不痛

2020年JAVA面试208题

面试是类似演讲演说的过程,网上的面试资料都是文字的,没办法让面试者直观的体验到面试过程,希望这个音频节目对你有帮助。纯粹硬核IT知识,技术小白请绕路。搜集整理各...

by:小崔爱读书

java面试特训营|随时随地学面试

不论你是否在找工作,都要时刻保持竞争力,掌握好java面试技能,随心所欲,找工作无惧1、一对一课程规划,避免盲目乱整浪费时间2、专业简历修改,高质量简历一投就中...

by:码农那点事