新建(New)、可运行(Runnable)、阻塞(Blocking)、无限期等待(Waiting)、有限期等待(Timed-Waiting)、死亡(Terminated)java
守护线程时提供通用服务的线程(例如垃圾回收线程),优先级很低
经过Thread对象的setDaemon(boolean)方法设置守护线程与用户线程,注意此方法必须在线程对象的start方法以前调用,不然会抛出java.lang.IllegalThreadStateException异常
守护线程建立的线程默认是守护线程,用户线程同理。
守护线程是为了服务用户线程而存在的,全部用户线程结束以后,jvm就退出了,守护线程天然也结束,因此守护线程的结束时间不肯定数据库
线程的sleep方法(静态方法),休眠当前线程,当前线程进入timed-waiting状态api
线程对象的yield方法代表该线程已经完成了最重要的工做,尝试让出cpu占用,把cpu使用权让给同优先级的其余线程安全
经过调用线程对象的interrput方法中断该线程,若是该线程处于等待/阻塞状态,会抛出java.lang.InterruptedException异常。
该方法不能中断处于I/O阻塞或synchronized阻塞的线程
线程对象的该方法被调用后,会设置阻断标志为true,经过interrupted()方法检查是否有人调用了本线程的interrupt方法多线程
检查是否有人调用了本线程的interrupt方法并发
线程池的shutdownNow方法就是经过调用全部工做线程的interrupt方法来中断工做线程jvm
https://www.cnblogs.com/darknessplus/p/10359256.htmlide
都是可重入锁
synchronized关键字由jvm实现,ReentrantLock由jdk实现
ReentrantLock提供比synchronized更高级的功能性能
ThreadLocal类
ThreadLocal 不是用来协调多线程的,而是为同一个线程的不一样方法提供共享变量。
一个线程的ThreadLocal变量在任何方法内都是可见的
线程Thread保存了ThreadLocalMap,ThreadLocalMap保存了本线程的全部ThreadLocal数据
ThreadLocal提供的方法
public T get() { } public void set(T value) { } public void remove() { } protected T initialValue() { }
多线程协做解决问题时,须要对他们的执行顺序进行协调
调用另外一个线程对象的join方法表示本线程等待另外一个线程执行完成后再继续执行
wait、notify是Object类提供的final方法,不可重写。
经过调用某个对象的wait方法,释放本线程对该对象持有的锁,进入阻塞状态。
另外一个线程调用该对象的notify方法,唤醒该对象的锁的阻塞队列中的一个线程,notifyAll方法唤醒该对象的等待队列的全部线程。
wait期间,线程会释放锁,否则会死锁。
配合synchronized使用,再同步代码中使用。
生产者消费者问题:
public class Wait { public static void main(String[] args) throws InterruptedException { LinkedList<Integer> list = new LinkedList<Integer>(); Factory factory = new Factory(); factory.setList(list); factory.setMaxSize(10); for(int i=1;i<=10;i++) { Producer producer = new Producer(); producer.setNum(i); producer.setFactory(factory); producer.start(); Consumer consumer = new Consumer(); consumer.setNum(i); consumer.setFactory(factory); consumer.start(); } } } class Producer extends Thread{ private AbstractFactory factory; private int num; public void setNum(int num) { this.num = num; } public void setFactory(AbstractFactory factory) { this.factory = factory; } @Override public void run() { factory.produce(num); } } class Consumer extends Thread{ private AbstractFactory factory; private int num; public void setFactory(AbstractFactory factory) { this.factory = factory; } public void setNum(int num) { this.num = num; } @Override public void run() { factory.consume(num); } } class Factory implements AbstractFactory{ private List<Integer> list; private int maxSize; public void setList(List<Integer> list) { this.list = list; } public void setMaxSize(int maxSize) { this.maxSize = maxSize; } public void produce(int num) { synchronized (list) { while(num+list.size()>maxSize) { try { System.out.println("仓库已满。要生产的"+num+",库存容量"+maxSize); list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int size=list.size(); for(int i=size;i<size+num;i++) { list.add(i); } System.out.println("生产"+num+"件,总共"+list.size()+"件"); list.notifyAll(); } } public void consume(int num) { synchronized (list) { while(list.size()-num<0) { try { System.out.println("仓库已空。要消费的"+num+",库存容量"+list.size()); list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int size=list.size(); for(int i=size-1;i>=size-num;i--) { list.remove(i); } System.out.println("消耗"+num+"件,总共"+list.size()+"件"); list.notifyAll(); } } } interface AbstractFactory { void produce(int num); void consume(int num); }
对应着Object的wait和notify方法,Lock也有相似的机制。
经过Lock.newCondition()方法获取一个condition对象,经过condition对象的await和signal方法进行线程同步。
在使用condition对象的await和signal方法以前必须得到重入锁,调用signal方法后最好释放重入锁。
控制一个线程等待其余线程
public static void main(String[] args) throws InterruptedException { final CountDownLatch count = new CountDownLatch(10); for(int i=0;i<10;i++){ new Thread(){ @Override public void run() { System.out.println(Thread.currentThread().getName()); count.countDown(); } }.start(); } count.await(); System.out.println("END"); }
输出:
Thread-0 Thread-2 Thread-3 Thread-1 Thread-5 Thread-4 Thread-6 Thread-7 Thread-8 Thread-9 END
信号量,控制并发线程数
public static void main(String[] args) { Semaphore semaphore = new Semaphore(1); for (int i = 0; i < 10; i++) { new Thread() { @Override public void run() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "正在运行"); Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println(Thread.currentThread().getName() + "结束"); semaphore.release(); } } }.start(); } }
输出:
Thread-5正在运行 Thread-5结束 Thread-0正在运行 Thread-0结束 Thread-3正在运行 Thread-3结束 Thread-8正在运行 Thread-8结束 Thread-6正在运行 Thread-6结束 Thread-2正在运行 Thread-2结束 Thread-7正在运行 Thread-7结束 Thread-1正在运行 Thread-1结束 Thread-4正在运行 Thread-4结束 Thread-9正在运行 Thread-9结束
得到任务的返回值
阻塞队列,在线程池里有应用
对数据更新的冲突持保守态度,认为总会发生冲突。策略是在处理数据时加锁
乐观锁认为发生冲突的状况比较少,不加锁,而是在更新数据的时候检查是否发生了冲突。
为数据库表增长版本号字段,每次更新数据版本号+1。在修改数据前获取版本号,提交修改时检查两次版本号是否一致,如不一致说明数据更新发生了冲突。
Compare And Swap
现值V、旧值A、新值B,当且仅当V==A,更新B到数据库
硬件实现的原子操做
CAS,V==A并不能说明V没有发生过改变
CAS适用读多写少,synchronized适用写多(冲突多)