Java线程

如何在Java中实现线程?|Java创建线程有哪几种方式?[面试7.0]

继承Thread: 使用start方法来开启线程,然后会调用线程子类的run方法
implements Runnable: 使用start方法来开启线程,然后会调用线程实现类的run方法
implements Callable: 使用start方法来开启线程,然后会调用线程实现类的call方法,call有返回值,且通过FutureTask的get可以获取线程的返回值
线程池实现: 传递7个参数,使用executesubmit开启执行线程

在具体多线程编程实践中,如何选用Runnable还是Thread?[面试5.0]

两个都不用,建议用线程池
不用的原因:
1.每次new Thread,新建对象性能差
2.缺乏统一管理,可能导致线程创建过多,死机
如果非要二选一,那么Runnable的优势如下
1.Runnable避免了Java单继承问题,使得线程子类可以继承其他类
2.Runnable解除了线程代码和任务代码的耦合

Thread类中的start()和run()方法有什么区别?[面试6.0]

线程Start后处于就绪状态(Runnable)->JVM调度线程执行线程的run->run结束后线程结束
如果直接调用run的话只是普通函数调用

Runnable和Callable有什么不同?[面试5.0]

Runnable接口run方法无返回值,Callable接口call方法有返回值
Runnable接口run方法只能抛出运行时异常,且无法捕获处理,Callable接口call方法允许抛出异常,且抛出的异常可以捕获

Java多线程中调用wait()和sleep()方法有什么不同?[面试6.0]

wait()是一种等待阻塞,运行的线程执行wait()方法,该线程会释放占用的所有资源,比如锁,JVM会把该线程放入"等待队列"中,不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒
sleep()使当前线程休眠,进入阻塞状态,时间一到自动唤醒当前线程,sleep不会释放锁

线程Thread有几种状态,怎么理解?[面试7.0]


初始状态(New)?新创建了一个线程对象,还没有调用线程的start时
就绪状态(Runnable)?也是可运行状态,调用start方法后,等待获取Cpu使用权
运行状态(Running)?就绪状态的线程获取了Cpu,执行程序代码

阻塞状态(Blocked)?
等待阻塞(Waiting,Timed_Waiting)?运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入"等待队列"中.进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒,Timed_Waiting:若在毫秒值结束之后还没有被notify()唤醒,就会自动醒来
同步阻塞?运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入"锁池"中
其他阻塞?运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态,当sleep()状态超时,join()等待线程终止或者超时,或者I/O处理完毕时,线程则变为就绪状态

死亡状态(Terminated): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期

yield()的作用: 让当前运行线程回到可运行状态,然后让所有线程重新竞争,这样就能使得相同优先级的线程之间能适当的轮转执行
join()的作用: 执行线程并等待线程的释放,它还可以将指定的线程加入到当前线程,比如在线程B中调用了线程A的join()方法,那么线程A执行完后执行线程B

wait(),notify()和notifyAll()方法为什么属于Object而不定义在Thread中?[面试7.2]

方便调用: 所有的类都继承Object类,所以这些方法放到Object类中便于线程之间通信
线程之间通讯是靠同步和锁实现的,若将这些方法放到Thread中时,一个线程会持有很多锁,当线程释放锁的时候并不知道要释放哪个锁,比较冗余,不好管理

多线程join方法用于什么场景?[面试7.0]

主线程会等待子线程执行完毕后才执行的场景,以及线程按顺序执行的场景

高并发环境下的计数器如何实现?[面试7.5]

synchronized方式实现
AtomicInteger或AtomicLong实现
LongAdder或LongAccumulator实现
ReentrantLock实现
CountDownLatch实现

LongAdder和AtomicLong的有什么区别:
LongAdder是基于分散式存储,在并发情况下,将另一个线程的值保存到新的变量中,最终获取值的时候进行合并,这样提升了并发性,缺点是统计的时候,若有并发更新,会导致数据有误

Java中如何停止一个线程?[面试7.0]

flag: 自定义flag标志让run内方法break

interrupt: 使用Thread的interrupt相关方法让run内方法break
Thread.interrupt()通知目标线程中断,也是设置中断标志位,中断标志位表示当前线程已经被中断了
Thread.isInterrupted()检查当前线程是否被中断(通过检查中断标志位)
Thread.interrupted()判断当前线程是否被中断,同时清除当前线程中断标志位状态

Java多线程中有哪些并发流量控制工具类?[面试6.0]

CountDownLatch
Semaphore
CyclicBarrier

多线程的类你在项目的实际研发过程中是否有使用过?[面试5.0]

STAR面试模型进行阐述:
利用AtomicLong的例子:
背景:需要一个简单的生成订单号的程序,并保证订单号在多线程下不重复
任务:写一个获取订单号的方法由时间加随机数组成,并且全局唯一
行动:利用AtomicLong可以保证多线程的原子性,使用它的自增部分生成随机数部分,并为了保证订单号长度,生成的随机数有一个允许的最大值,超过这个值后,当前线程休眠很小的时间,并初始化AtomicLong的值,然后再次生成
结果:由于订单号是时间明确到毫秒+随机数,这样操作后可以保证订单号不重复
利用ConcurrentHashMap的例子:
背景:需要一个变量来统计在线人数,并保证多线程下的数据正确
任务:写一个变量在多线程下当Session登录后保存该Session的值,用户注销时删除
行动:利用ConcurrentHashMap全局变量进行put方法添加,remove进行删除,保证了线程的安全
结果:可以直接访问ConcurrentHashMap对象的keys或得到有多少用户在线
使用CountDownLatch和Thread+消息队列的例子:
背景:需要一个程序来进行多线程并发单元测试一个抢现金券的功能,要求同一时刻有很多并发线程同时执行
任务:写一个程序控制线程可以同时并发,请求一个抢现金券的消息队列消费者接口,保证系统能正常运行
行动:写一个CountDownLatch+await控制线程同时并发,限制消息队列的流量(x-max-length)
结果:可以看到并发执行结果,有线程同时进行抢现金券,服务生产端不停产生现金券,消费端消费现金券

如何在多个线程间共享数据?[面试6.0]

利用共享变量,需要保证这个共享变量是线程安全的,比如ConcurrentHashMap,ThreadLocal,volatile等
多个线程之间传参数也可以

有多个线程T1,T2,T3怎么确保它们按顺序执行?[面试6.0]

join方法,可以使用主线程的join也可以使用子线程的join

什么是线程隔离(线程封闭)?[面试6.0]

线程隔离是指将一个对象封闭到一个线程,只有这一个线程能访问这个对象,不会出线程安全问题,例如连接JDBC时,首先在线程池中获取一个Connection对象,使用完后将这个对象还给连接池,由于大多数操作都是同步的,所以相当于将Connection对象封装到了单个线程中,再如(ThreadLocal)

线程什么时候会产生死锁?[面试6.0]

死锁: 多个线程相互等待,导致程序无法继续往下运行
产生死锁的例子: 有两个线程,T1,T2,两个对象O1,O2
T1需要锁定O1才能继续执行,但发现O1被T2锁定了,需要等待T2释放O1
T2需要锁定O2才能继续执行,但发现O2被T1锁定了,需要等待T1释放O2
这样就造成了相互等待,即产生了死锁

如何避免死锁:
按顺序加锁: 比如让T1执行完后再让T2执行,可以使用Join的方式
设置加锁超时: 如果出现死锁,超时后可以自动释放锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2023年Java面试宝典

您的鼓励是对我的肯定,共建希望

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值