01-多线程

java thread

synchronized

  • 类锁

    • 修饰static函数和synchronized(ClassName.class)都是获取类锁
  • 对象锁

    • 修饰成员函数和synchronized(this|object)都是对象锁
    • 其中修饰成员函数和synchronized(this)获取的都是当前类对象的锁
  • 优点

    • 简单,易用
    • 开销少
  • 缺点

    • 可重入性差
    • 大量使用可能导致性能下降
  • 推荐用法

    • 单例模式使用
    • 用于计数器的自增或类似场景

Object.wait, Object.notify, Object.notifyAll

函数作用顾名思义

wait: 先释放对象锁,等待notify/notifyAll后释放
也就是说,可以基于他们实现条件变量, pv操作

native

  • join: 让调用线程等待其结束
  • yeild: 暂时让出时间片
  • sleep: sleep
  • interrupt: 打断执行
    • 调用后,线程中的一些任务可能产生InterruptedException
    • interrupted(): 线程中判断是否被打断,若中断,返回true,并清除标志位(下一次一定返回false),try-catch InterruptException也会导致标志位清除
    • isInterrupted(): 测试是否被打断,若中断,返回true,但不清除标志位(下一次一定返回与上一次相同)

Callable

  • 实现Callable,能获取返回状态

守护线程

在start()前,调用setDaemon(true)即可创建。类似于守护进程,是一直存在运行的线程。由于jvm的存在,若主线程退出,其他线程运行结束后会退出,

其他

  • ThreadLocal

    • 相当于pthread的每线程存储
    • 一个包装器,包装任何类型后,调用get,set方法,获取/修改当前线程中的值
  • java线程生命周期

GC Roots

在GC时,如何判断一个对象是否可回收,就是看其是否直接/间接被GC Roots引用,GC Roots一般包括

  • 系统类加载器加载的类: Class: Classes loaded by a system class loader; contains references to static variables as well
  • 当前栈中的对象: Stack Local: Local variables and parameters to methods stored on the local stack
  • 活跃的线程: Active Java Threads: All active Java threads
  • JNI(native代码)引用的对象: JNI References: Native code Java objects created for JNI calls; contains local variables,parameters to JNI methods, and global JNI references

Additionally, there are a few more possible types of GC Roots:

  • 监视器监视的对象: Objects used as monitors for synchronization
  • 由JVM实现定义的特定对象: Specific objects defined by the JVM implementation that are not garbage collected for its purpose. That might contain important exception classes, system class loaders, or custom class loaders

内存泄露

要注意内存泄露,非静态的内部类会持有外部的对象,若内部类是一个线程,则会导致外部对象(如Activity)无法释放,导致内存泄露

几种多线程工具的选择

  • AsyncTask(已弃用): 小而短的任务,后台任务需要推到前台

  • Executor: 推荐使用,后台任务执行,不需要推回前台

  • Handler: 可以把任务推到前台

  • HandlerThread: 把一个任务推到后台的一个线程中

  • Service: 不是线程,他是后台任务的活动空间(存后台任务的状态)

  • IntentService: 线程中使用context时

isInterrupted 和 interruptd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public boolean isInterrupted() {
return interrupted;
}

public static boolean interrupted() {
return currentThread().getAndClearInterrupt();
}

boolean getAndClearInterrupt() {
boolean oldValue = interrupted;
// We may have been interrupted the moment after we read the field,
// so only clear the field if we saw that it was set and will return
// true; otherwise we could lose an interrupt.
if (oldValue) {
interrupted = false;
clearInterruptEvent();
}
return oldValue;
}

private static native void clearInterruptEvent();
作者

Meow Meow Liu

发布于

2023-09-21

更新于

2024-04-23

许可协议

评论