三明北京网站建设软文通
目录
并行和并发有什么区别?
线程和进程有什么区别?
创建线程有哪几种方式?
runnable和callable有什么区别?
线程的状态及转换?
sleep()和wait()的区别?
run()和start()有什么区别?
在Java程序中怎么保证多线程的运行安全?
什么是悲观锁?
什么是乐观锁?常见的两种实现方式?有什么缺点?
无泪的憋屈缝成了一张隐形披风偶而还能抵挡酷寒,无用的大喊苦苦等到的回声只是力气放尽的绝望🌹
话不多说,发车!
并行和并发有什么区别?
- 并行是指两个或多个事件在同一时刻发生,在不同的实体上
- 并发是指两个或多个事件在同一时间间隔发生,在同一个实体上
线程和进程有什么区别?
- 进程是资源分配的基本单位,进程有独立的内存单元,一个进程中可以有多个线程
- 线程是CPU调度的基本单位,多个线程之间可以共享资源,同一个进程中的多个线程可以并发执行
- 线程相比进程能够减少开销:线程的创建快于进程;线程的终止快于进程;同一个进程内的多个线程切换比进程快
创建线程有哪几种方式?
1、继承thread类,重写run方法
package juc.thread;public class MyThread extends Thread{@Overridepublic void run(){int i = 0;while (true){if(i == 100) break;i++;}System.out.println(i);}public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();}
}
2、实现runnable接口,重写run方法
package juc.thread;public class MyThread implements Runnable{@Overridepublic void run() {int i = 0;while (true){if(i == 100) break;i++;}System.out.println(i);}public static void main(String[] args) {MyThread myThread = new MyThread();Thread thread = new Thread(myThread);thread.start();}}
3、使用callable和futureTask:实现callable接口,再使用future类来包装callable对象
package juc.thread;import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;public class MyThread {public static void main(String[] args) {MyThread myThread = new MyThread();FutureTask<Integer> futureTask = new FutureTask<>((Callable<Integer>)()->{return 1;});new Thread(futureTask,"有返回值的线程").start(); }}
4、使用线程池:Excutor框架
runnable和callable有什么区别?
@FunctionalInterface
public interface Runnable {/*** When an object implementing interface <code>Runnable</code> is used* to create a thread, starting the thread causes the object's* <code>run</code> method to be called in that separately executing* thread.* <p>* The general contract of the method <code>run</code> is that it may* take any action whatsoever.** @see java.lang.Thread#run()*///返回值是voidpublic abstract void run();
}
@FunctionalInterface
public interface Callable<V> {/*** Computes a result, or throws an exception if unable to do so.** @return computed result* @throws Exception if unable to compute a result*/V call() throws Exception;
}
- runnable接口中的run方法没有返回值,callable接口中的call方法有返回值
- runnable接口中run方法的异常必须在内部处理,不能抛出;callable接口中的call方法的异常可以在内部处理,也可以向上抛出
线程的状态及转换?
- new:初始状态,线程被构建,但是还没有调用start方法
- runnable:运行状态
- blocked:阻塞状态,表示线程阻塞于锁
- waiting:等待状态,进入该状态的线程需要其他线程做出一些特定动作,通知或中断
- time_waiting:超时等待状态,但是可以在指定的时间内自行返回
- terminated:终止状态,线程已经执行完毕
sleep()和wait()的区别?
- 都可以暂停线程的执行
- sleep方法在睡眠指定时间后,可以自动苏醒;wait方法需要notify和notifyAll来唤醒
- sleep是Thread类的静态方法;wait是Object的方法
- sleep不会释放锁;wait会释放锁
run()和start()有什么区别?
- 当调用start方法时,start会启动一个线程,此时线程处于就绪状态,只有当得到时间片以后才会运行run()中的代码,此时无需等待run方法中的代码执行完即可执行下面的代码,所以说start真正的实现了多线程
- 当调用run方法时,程序中依然只有主线程这一个线程,只有等到run方法中的代码执行完之后才能继续执行下面的代码,所以说run方法只是一个普通方法
在Java程序中怎么保证多线程的运行安全?
- 原子性:在同一时刻只能有一个线程对数据进行修改
- 可见性:线程对主内存的修改要及时地被其他线程看到
- 有序性:遵循happens-before原则:如果一个操作happens-before另一个操作,那么第一个操作的执行结果对于第二个操作来说是可见的,而且第一个操作的执行顺序排在第二个操作之前;两个操作存在happens-before关系,并不意味着Java平台的具体实现按照这个顺序来执行,如果重排序之后的结果不会被改变,这种排序就是合法的
什么是悲观锁?
它认为多线程同时修改资源的概率比较高,很容易出现冲突,所以它在访问资源之前需要先加锁,synchronized就是基于这种思想;主要用于写比较多的情况
什么是乐观锁?常见的两种实现方式?有什么缺点?
它会先修改资源,再验证这段时间内有没有其他线程正在修改资源,如果没有,那么操作完成;如果有,就放弃本次操作;因为它全程没有加锁,所以又叫无锁编程;主要用于多读或者加锁成本比较高的场景
实现方式:
- 版本号机制:在数据表中添加了version字段,表示数据被修改的次数。当数据被修改时,version加1。当提交更新时,如果之前读到的version值和数据库中的version值一致,则提交更新。否则进行重试,直到成功。
- CAS算法:compare and swap。该算法涉及到三个值:需要读写的内存值V,进行比较的值A,拟写入的值B,当且仅当V=A时,才会进行原子方式将V更新为B,否则就会重新尝试
缺点:
- 如果一个变量V在初次读取到的时候是A值,在准备赋值的时候仍然是A值,那么CAS操作就会误认为该值中间没有被更新过
- 自旋CAS如果长时间不成功,会对CPU带来非常大的开销
- CAS只对单个共享变量有效,即只能保证对一个变量的原子操作,对多个共享变量无效
整理面经不易,觉得有帮助的小伙伴点个赞吧~感谢收看!