**Java多线程学习**
1.线程的生命周期
2.实现线程的两种方式
(1)extend Thread (2)implement Runnable
3.Runnable 的好处
(1)Runnable讲线程的控制和方法给分开了,将线程给封装起来,使其更加面对对象。
(2)避免了线程单继承的局限性
4.一些创建线程的知识
Stacksize的作用是设置线程的栈的大小的,如果不设,jvm会自动给一个。它是高度平台依赖的,有可能有点平台不支持
ThreadGroup如果不设置,会自动设置为父线程的threaGroup
5.daemon线程会随着主线程的结束而结束。
6.优先级你就算设置了也不一定有用。
7.如果某个子线程写了join(),那么父线程会等待这个子线程结束后才会结束。
8.Interrupt能够打断的是正在sleep,wait,和join的线程。
9.Sleep和wait的区别
(1)sleep是线程的方法,但是wait是对象的方法。
(2)Sleep不释放锁,wait释放锁,并加入monitor队列中。
(3)Sleep不依赖monitor,wait依赖。
(4)Sleep不需要别的线程唤醒,wait需要(除了wait(10))
10.volatile的作用:
(1)可见性 说到可见性,先说线程执行的时候要读取一个对象,一旦读取后,该线程就会把这个对象的值放缓存catch中,线程以后的每次读取都是访问缓存中这个值(一定时间内)。在这期间,有别的线程改变了内存中的这个对象,但是本线程的缓存并没有改变,这样导致了这个线程在这个时间段内访问的都是久的数据。
Volatile的作用就是保证线程读取这个对象都是最新的值,对象一旦加上volatail 而且有多个线程引用这个对象时,线程就会去主存中查而不会一直在catch中读这个数。
(2)保证有序性。一旦加上volatile关键字,对象的创建就必须按顺序来,对象创建一共有这几步,1.装载 2.链接(验证,准备,解析) 3.初始化 你在创建的时候可能时123,也可能是132.加上volatile就必须按123走。 在你按132走个过程中,你先对类进行了初始化,但是该类的变量还没有分配内存,你在访问的时候就会发生空指针异常。
但是volatile不保证原子性。一个线程从内存中拿到一个对象的值,对它进行了+1但还没有写回内存的时候,另一个线程也从内存中拿到这个对象的值,也+1,当第一个线程写入内存后,第二个线程也写入内存。但只加了一次。