好比一个main方法里面前后运行thread1,,thread2,thread3,那么thread1.start()以后,运行thread1.join(),这是会让主线程mian等待新的线程thread1执行完了,再执行主线程mian下面的代码,thread1.join()是然主线程main wait。java
package com.java.yj; /** * Created by yejian on 2018/7/9. */ public class MultiThread { public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(new Thread1()); thread1.start(); thread1.join(); Thread thread2 = new Thread(new Thread2()); thread2.start(); thread2.join(); Thread thread3 = new Thread(new Thread3()); thread3.start(); } public static class Thread1 implements Runnable{ @Override public void run() { System.out.println("Thread1"); } } public static class Thread2 implements Runnable{ @Override public void run() { System.out.println("Thread2"); } } public static class Thread3 implements Runnable{ @Override public void run() { System.out.println("Thread3"); } } }
java5之后提供的一个多线程操做方法,建立一个只有一个线程的线程池操做,会建立一个线程队列,按FIFO的顺序执行里面的线程。编程
package com.java.yj; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by yejian on 2018/7/9. */ public class MultiThread2 { public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(new Thread1()); executor.submit(new Thread2()); executor.submit(new Thread3()); executor.shutdown(); } public static class Thread1 implements Runnable{ @Override public void run() { System.out.println("Thread1"); } } public static class Thread2 implements Runnable{ @Override public void run() { System.out.println("Thread2"); } } public static class Thread3 implements Runnable{ @Override public void run() { System.out.println("Thread3"); } } }
解决并发过程当中如何处理可见性,原子性,有序性的问题
runnable ,thread。
并发编程中的2个关键问题:缓存
a. 线程间如何通讯 --wait() notify() notifyAll()
a) 共享内存 -隐式通讯
b) 消息传递 - 显示通讯多线程
b. 线程之间如何同步
在共享内存的并发模型中,同步是显示作的; synchronized
在消息传递的并发模型中,因为小时发送必须在消息接受以前,因此同步是隐式的并发
什么对象是内存共享的 ,什么不是,堆内存的对象,java虚拟机栈
JMM定义了线程和主内存之间的一个关系。线程之间通信,必须经过主内存通信。jvm
volatile、synchronized
volatile 功能,声明了volatile的变量,进行写操做的时候,jvm会向处理器发送一条Lock的前缀指令,会把这个变量所在缓存行的数据写回到系统内存。
在多处理器的状况下,保证各个处理器缓存一致性的特色,会实现缓存一致性协议。改变了值的volatile变量,在其余行程被指为失效状态其余线程要使用这个变量,须要从新到驻村里面去取。ide
synchronized:可重入锁、互斥性、可见性
volatile 能够作到原子性,可见性,不能作到复合操做的原子性性能
好比: volatile int i;
i++ 读取i的值,给i加1,把新的值赋值给i,这个i++操做在多线程环境下是没法保证原子性的优化
synchronized后面锁定的对象,能够是一个类对象,也能够是一个成员变量。
第一个线程进来调用monitorener 和monitorexit实现,获取对象的监视器,释放对象监视器
后续进程过来,若是monitor尚未释放,那么他获取不到这个对象的monitor,会放到一个对列里面:synthronizedQueue。 等到对象的锁释放了,通知synthronizedQueue出队列,获取那个monitor。线程
Lock是java5之后出现的,在juc包: java.util.concurrentlocks
1.1 获取锁的线程执行完了该代码块 1.2 线程出现异常
2.1 读写冲突
ReadWriteLock
ReadLock
WriteLock
ReenterantLock可重入锁
可中断锁
公平锁 等待一个锁的实际越长,获取这个锁的概率越高
ReenterantReadWriteLock 可重入读写锁
Lock是java里面的一个接口,有丰富的实现,而synchronized是java的一个关键字,是一个内置的功能
竞争资源激烈的状况,Lock性能优于synchronized,可是jdk7,8对synchronized作了不少优化,性能差别不大。