keywordsSet.add("james");
keywordsSet.add("13号技师");
// 使集合不可修改
keywords = Collections.unmodifiableSet(keywordsSet);
}
}
* 将一个对象引用保存在volatile类型的域或者是AtomicReference对象中。
class JamesVolatile {
private volatile String state;
void setState(String state) {
this.state = state;
}
String getState() {
return state;
}
}
* AtomicInteger将值存储在volatile字段中,因此volatile变量的相同规则适用于此处。
class JamesAtomics {
private final AtomicInteger state = new AtomicInteger();
void initializeState(int state) {
this.state.compareAndSet(0, state);
}
int getState() {
return state.get();
}
}
* final域, 将对象的引用保存到某个正确构造对象的final类型的域中。
class JamesFinal {
private final String state;
JamesFinal(String state) {
this.state = state;
}
String getState() {
return state;
}
}
确保此引用在构造期间不逃逸。
this引用逃逸("this"escape)是指对象还没有构造完成,它的this引用就被发布出去了。这是危及到线程安全的,因为其他线程有可能通过这个逸出的引用访问到“初始化了一半”的对象(partially-constructed object)。这样就会出现某些线程中看到该对象的状态是没初始化完的状态,而在另外一些线程看到的却是已经初始化完的状态,这种不一致性是不确定的,程序也会因此而产生一些无法预知的并发错误。在说明并发编程中如何避免this引用逸出之前
class JamesThisEscapes {
private final String name;
ThisEscapes(String name) {
JamesCache.putIntoCache(this);
this.name = name;
}
String getName() {
return name;
}
}
class JamesCache {
private static final Map<String, ThisEscapes> CACHE = new ConcurrentHashMap<>();
static void putIntoCache(JamesThisEscapes thisEscapes) {
//“this”引用在对象完全构造之前逃逸
CACHE.putIfAbsent(thisEscapes.getName(), thisEscapes);
}
}
* 正确同步成员变量。
class JamesSynchronization {
private String state;
synchronized String getState() {
if (state == null)
state = "Initial";
return state;
}
}
## **第6节 不可变的对象**
不可变对象具备执行安全的特性。此外,相较于可变对象,不可变对象通常也较合理,易于了解,而且提供较高的安全性。不可变对象的一个重要特性是它们都是**线程安全的**,因此不需要同步。当然对象不可变的是有如下要求滴:
* 所有变量都是?`final.`
* 所有变量必须是可变对象或不可变对象。
* `this`?在构造方法执行期间引用不会逃脱。
* 该类是final,因此无法在子类中覆盖此行为。
**不可变对象的示例:**
// 声明为final类
public final class JamesArtist {
// 不可变对象, 字段为final
private final String name;
//用于保存不可变对象, final类型
private final List<JamesTrack> tracks;
public JamesArtist(String name, List<JamesTrack> tracks) {
this.name = name;
//防止拷贝
List<JamesTrack> copy = new ArrayList<>(tracks);
//标记为不可更改
this.tracks = Collections.unmodifiableList(copy);
// “this”在构造期间不会传递到任何地方。
}
}
// 同上声明为final类
public final class JamesTrack {
// 不可变对象, 字段为final
private final String title;
public JamesTrack(String title) {
this.title = title;
}
}
## **第7节 线程Thread类**
`java.lang.Thread`类用于表示应用程序或JVM线程。代码总是在某些Thread类的上下文中执行(用于 `Thread#currentThread()`获取自己的Thread)。
**线程状态如下**
![](https://s2.51cto.com/images/20210829/1630172515504500.jpg)
**线程协调方法如下**
![](https://s2.51cto.com/images/20210829/1630172515854097.jpg)
### **怎么处理 InterruptedException异常?**
* 在重新抛出 InterruptedException 之前执行特定于任务的清理工作。
* 声明当前方法抛出?`InterruptedException.`
* 如果未声明某个方法抛出?`InterruptedException`,则应通过调用将中断的标志恢复为true,?`Thread.currentThread().interrupt()`并且应该抛出一个更合适的异常。将标志设置为true非常重要,以便有机会处理更高级别的中断。
### **不可预知的异常处理**
线程可以指定 `UncaughtExceptionHandler`将接收任何导致线程突然终止的未捕获异常的通知。
Thread thread = new Thread(runnable);
thread.setUncaughtExceptionHandler((failedThread,exception)->
{
logger.error("Caught unexpected exception in thread
‘{}’.", failedThread.getName(), exception);
}
);
thread.start();
## **第8节 线程的活跃度**
### **死锁**
当存在多个线程时会发生死锁,每个线程等待另一个线程持有的资源,从而形成资源循环和获取线程。
**潜在的死锁示例:**
class JamesAccount {
技术学习总结
学习技术一定要制定一个明确的学习路线,这样才能高效的学习,不必要做无效功,既浪费时间又得不到什么效率,大家不妨按照我这份路线来学习。
最后面试分享
大家不妨直接在牛客和力扣上多刷题,同时,我也拿了一些面试题跟大家分享,也是从一些大佬那里获得的,大家不妨多刷刷题,为金九银十冲一波!
最后,若需要完整pdf版,可以点赞本文后点击这里免费领取
原创文章,作者:kepupublish,如若转载,请注明出处:https://blog.ytso.com/123384.html