JAVA多线程是为了提高程序利用率,而不是程序执行速度。
并行:多个CPU或多台机器同时执行一段处理逻辑,是真正意义上的同时。
并发:多个线程争抢公共资源,这时系统会通过CPU调度算法来调节线程,实际上线程不是同时工作。
Volatile
volatile是什么?它是一个修饰符,修饰变量,被修饰的变量只能从内存中读取数据。为什么要从内存中读呢?这就涉及到高速缓存的问题,因为CPU会把数据放到缓存里面做个副本,在计算完毕之后再把缓存里面的值更新到内存,这是一种提高程序运行效率的方法。而变量经过volatile修饰后,线程就将缓存里面的副本视为无效,直接从内存里面读取,其他线程也是如此,一定程度上提高了线程安全性。但是他一定是线程安全的吗?不是!若不做同步处理,还是会有脏读脏写的情况。
volatile还有一个隐藏属性——禁止指令重排序,用volitale修饰的变量被使用时,该行之前的代码都会被执行完毕,之后的代码一定未被执行。
线程实现的两种方式:
1——继承Thread类,重写run方法
2——实现Runable接口,重写run方法
他们的实例化是不同的,还是有点东西的。
Run方法和Start方法有什么区别?
Run就是在当前线程里执行线程的Run方法,不新建线程。
Start就是待获取到CPU资源后新建线程去执行Run方法,要新建线程。
线程的执行顺序
接下来我在线程A和线程B里写了一个循环,连续5次向屏幕输出内容。运行结果如下:
此时线程A B各管各的,输出的内容就可能混在一起。
好的,然后我在线程A的Start方法后面加了一句让线程A休眠两秒,再启动线程B。输出的结果就是前面都是A,隔两秒才到B。
这就说明了,线程的Sleep方法是真的要等他休息完才会执行下一行代码,而不是发一个信号让他休息就接着跑。
接下来说说join,Thread中,join()方法的作用是调用线程等待该线程完成后,才能继续往下运行。
join的用法,我贴个代码上来,运行结果也有。
yeiled 是让当前线程先释放资源,但是它仍然会去争取下一次的资源,所以说会出现刚刚yeiled然后又是它执行的情况。
sleep 是线程休眠,休眠期间它不会释放他持有的资源。
接下来敲敲加锁Sychronized
线程CD代码部分就是加减法太过简单就不放出了,可见,为这个取钱的方法加锁之后保证了数据不会混乱。
可能你们想看看混乱的数据,那我放出来,这种情况在数据库里叫脏读脏写。
2018-9-7先写到这儿,同步部分我还不懂,后面再补充。
2018-9-20时间过得这么快嘛。。。。。。。
现在敲了敲线程的同步,就两个方法,第一种,给方法加锁,第二种,使用Object对象加锁。
下面是一个线程A B 交替输出的例子,知识点:怎么加object锁,循环,object是先wait()还是先notify()。
package defaultPk;
public class LearnThread {
public static class MyThread extends Thread{
public Object object;
public String name;
public MyThread(String name,Object object){
this.name=name;
this.object=object;
}
@Override
public void run() {
synchronized (object) {
while (true) {
try {
System.out.println("Thread" + name);
object.notifyAll();
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args){
Object object=new Object();
MyThread t1=new MyThread("1",object);
MyThread t2=new MyThread("2",object);
t1.start();
t2.start();
}
}