1.Java的多线程来源
1.西计算硬件系统的支持,cpu是多核处理器,计算机体系本来就是多个数据来源。
2.Java的线程
1.Java线程的类型
1.Thread
Thread实现Runable接口
// Thread 实现Runnable接口
public class Thread implements Runnable {}
// Thread内部定义的线程生命周期的状态
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
Thread中的构造方法
Thread中的public方法
run()和start()的区别 ,run()是在同一线程开启执行方法,start()通过native方法开启新的线程等待系统调用执行。
@Override
public void run() {
if (target != null) {
target.run();
}
}
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
// Android-changed: Replace unused threadStatus field with started field.
// The threadStatus field is unused on Android.
if (started)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
// Android-changed: Use field instead of local variable.
// It is necessary to remember the state of this across calls to this method so that it
// can throw an IllegalThreadStateException if this method is called on an already
// started thread.
started = false;
try {
// Android-changed: Use Android specific nativeCreate() method to create/start thread.
// start0();
nativeCreate(this, stackSize, daemon);
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
wait()和sleep()的区别,wait()放弃了cpu的占用,sleep()占用了cpu的运行在等待.
2.Runable
3.Callable和Future
2.线程操作,中断,合并,让出,睡眠
3.线程同步操作Synchronized和Volatile,Lock
synchronized:作用于方法上和对象上,使方法和对象只能被一个线程访问。每一个查询都是一个内核操作。
volatile:使用于数据,使对数据的操作成为一个整体。不被多线程分割成多步骤。
lock:
synchronized和lock的区别:1.synchronized自动释放,lock手动释放。2.synchronized是语言提供的关键字在jvm层面提供实现机制,lock是Java方法提供的类用户可以自定义。3.synchronize d不可以获取到获取锁的状态,lock可以获取到获取锁的状态这样用户可以根据状态处理下一步的运行。4.synchronized是可重入锁,不可以中断,非公平,lock锁是可重入,公平,可判断。
4.CAS机制
CAS的全称为compare and swap简单的解释为比较交换,CAS有三个操作数,内存V,旧的预期值A,要修改的新值B,当且仅当预期值A和内存值相同时,将内存值V修改成B,否则什么都不做。这个过程发生在内存中的,是汇编语言的一个操作过程。那么乐观锁为什么用CAS算法呢?简单的来说就是乐观锁每次操作的时候都认为不会发生并发,但是为了安全还是会去检测是否并发了,这样的话不用sync耗费太大性能。
5.ThreadLocal
6.计数工具Atomic*类的数据
Atomic包是java.util.concurrent下的另一个专门为线程安全设计的Java包,包含多个原子操作类。
-
标量类:AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference
-
数组类:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray
-
更新器类:AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater
-
复合变量类:AtomicMarkableReference,AtomicStampedReference
原理分析:
unsafe在sum.misc包中,直接操作对象内存,修改jvm运行时的数据操作上不是通过类修改地址,而是直接通过地址修改数据。通过代码可以看出保证原子性是通过自旋+cas乐观锁。在这个过程中,通过compareAndSwapInt比较更新value值,如果更新失败,重新获取旧值,然后更新。
CAS相对于其他锁,不会进行内核态操作,有着一些性能的提升。但同时引入自旋,当锁竞争较大的时候,自旋次数会增多。cpu资源会消耗很高。
换句话说,CAS+自旋适合使用在低并发有同步数据的应用场景。
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long VALUE;
static {
try {
VALUE = U.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
private volatile int value;
/**
* Creates a new AtomicInteger with the given initial value.
*
* @param initialValue the initial value
*/
public AtomicInteger(int initialValue) {
value = initialValue;
}
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
return U.getAndAddInt(this, VALUE, 1);
}
}
其中的getAndAddInt方法我们再找源码
// var1:对象的引用
// var2:值的偏移量
// var3:期望值
// var4:更新值
//这个方法的作用就是拿着对象的引用以及位偏移量从内存中拿到值,然后拿着这个值和期望值进行一个比较,如果相同则将要更新的值放到内存中返回true如果不同则返回false.
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);//1
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//2
return var5;
}
7.java8做出的改进
在Java 8中引入了4个新的计数器类型,LongAdder、LongAccumulator、DoubleAdder、DoubleAccumulator。他们都是继承于Striped64。较之之前的技术工具引入了分段锁的概念。当竞争不激烈的时候,所有线程都是通过CAS对同一个变量(Base)进行修改,当竞争激烈的时候,会将根据当前线程哈希到对于Cell上进行修改(多段锁)。
3.Java线程池
1.
4.多线程的容器
1.容器的安全性
BlockingQueue
5.多线程的常见框架
Rxjava框架
6.Android中多线程的同步
Handle机制
7.Android中多线程的常见工具整理