• 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 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 tracks;

public JamesArtist(String name, List tracks) {
this.name = name;
//防止拷贝
List 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)。

线程状态如下

状态描述
NEW没有开始。
RUNNABLE启动并运行。
BLOCKED在监视器上等待 – 尝试获取锁并进入关键部分。
WAITING等待另一个线程执行特定操作(notify/notifyAllLockSupport#unpark)。
TIMED_WAITING相同WAITING,但是为等待超时。
TERMINATED停止。

线程协调方法如下

线程方法描述
start(启动)启动Thread实例并执行其run()方法。
join(阻止)阻止直到Thread完成。
interrupt(中断)中断线程。如果线程在响应中断的方法中被阻塞,InterruptedException则将在另一个线程中抛出一个线程,否则将设置中断状态。
stop(停止), suspend(暂停), resume(恢复), destroy(销毁)这些方法都已弃用。根据相关线程的状态执行的操作不安全。

怎么处理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 {
private long amount;

void plus(long amount) {
this.amount += amount;
}

void minus(long amount) {
if (this.amount < amount)
throw new IllegalArgumentException();
else
this.amount -= amount;
}

最后为了帮助大家深刻理解And

roid相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节

还有高级架构技术进阶脑图、Android开发面试专题资料帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
g-sOod6gdr-1647688672419)]

[外链图片转存中…(img-jJ0nY09o-1647688672420)]

[外链图片转存中…(img-eLO1vefm-1647688672420)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。