问:线程和进程的区别?
答:根本区别:进程是系统划分资源的最小单位,线程是cpu执行和调度的最基本单位。进程包含线程,进程内可包含多个线程。
问:为什么要使用多线程?
答:提高cpu利用率,并且线程切换和调度成本远小于进程。
问:什么是线程死锁?如何避免线程死锁?
线程死锁是指,在多线程情况下,A线程持有锁需要B线程所占有的资源,B线程持有锁需要A线程占有的资源,两个互相掣肘,导致线程死锁。
解决办法:1、尽可能的让某个线程在申请资源时,一次性的占有所需要的全部资源。
2、锁排序:指定锁的获取顺序,规定只有获取到A锁的线程才有资格获取B锁,同时获取到两个锁的线程才能对资源进行操作。
具体代码如何实现呢?答:可以采取嵌套锁,先获取A锁,再获取B锁
public synchronized void transferTo(BankAccount target, int amount) {
// 获取转出账户的锁
synchronized (this) {
// 获取转入账户的锁
synchronized (target) {
if (balance >= amount) {
this.balance -= amount;
target.balance += amount;
System.out.println("转账成功,转出账户余额:" + this.balance + ",转入账户余额:" + target.balance);
} else {
System.out.println("转账失败,转出账户余额不足");
}
}
}
}
问:代码中如何创建线程?
答:三种方式:
- 继承Thead类重写run方法,调用start方法,开启线程。调用start方法底层会调用start0方法开启线程。
- 实现Runnable接口,重写run方法,创建Thread类传入实现类,调用start方法开启线程。
- 实现Callable接口,重写call方法,创建一个
ExecutorService
对象,调用ExecutorService
的submit()
方法,将Callable
对象传递给它。这将返回一个Future
对象,您可以使用它来获取Callable
的执行结果。
// 创建一个固定大小的线程池
ExecutorService executor = Executors.newFixedThreadPool(1);
// 创建 Callable 对象的实例
Callable<Integer> callable = new MyCallable();
// 提交 Callable 对象给线程池执行
Future<Integer> future = executor.submit(callable);
问:Thread类、Runnable接口创建线程、Callable接口创建线程有什么区别?
Thread类只能继承,继承后不能再继承其他类,其他两个接口可以实现多个;Runnable接口不会返回结果和抛出异常,但Callable接口会返回执行结果和抛出异常。
问:wait方法和sleep方法的区别?
答:sleep方法不会释放锁,wait方法会释放锁,sleep方法只是让当前线程休眠,如果当前线程持有锁,不会释放锁,当休眠结束后线程自动苏醒,仍旧会执行当前线程。
wait方法也是让当前线程阻塞,但不一样的是,wait方法不会去自动苏醒,并且它会释放当前线程持有的锁,只有当另外一个线程调用休眠线程的notify方法才会苏醒。这也就完成了线程之间的通信。
标签:balance,获取,方法,接口,Callable,面试,线程,多线程,合集 From: https://blog.csdn.net/m0_53327171/article/details/136740039