java并行程序基础
参考:
https://github.com/chengbingh...
2.1 有关线程, 需要知道的事
进程是线程的容器
线程状态图:
2.2 线程的基本操作
2.2.1新建线程
2.2.2终止线程
stop 暴力终止线程,废弃方法
2.2.3线程中断
方法:
2.2.4 等待(wait)和唤醒notify
注意:
wait 是object的一个方法,调用wait方法的对象,必须在synchronized 中,因为要获取它的监视器。
wait会释放锁
public class SimpleWN {
final static Object obj = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(obj) {
System.out.println("t1.start,and t1 will wait");
try {
// 调用wait 方法的这个对象必须被synchronizeed
//wait 会释放锁
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1 was notify");
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(obj){
System.out.println("t2 start and will notify t1");
// 调用notify 方法的这个对象必须被synchronizeed
//如果 有n个线程此时都是由于调用了obj.wait方法,那么会唤醒任意一个
obj.notify();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2 end run");
}
}
});
t1.start();
t2.start();
}
}
输出:注意锁
t1.start,and t1 will wait
t2 start and will notify t1
t2 end run
t1 was notify
2.2.5 挂起(suspend)和继续执行(resume)
suspend()和resume方法
2.2.6 join 和yeild
join:加入,把线程当做一个方法了。
yeild:让出线程执行权,但是还是会争夺线程的执行权
2.3 volatile 与java 内存模型(JMM)
JMM: 原子性,可见性,有序性
原子性:32位虚拟机中多线程读写long不会有问题,但是不能保证i++
可见性:
虚拟机在-server模式下会进行优化,下面的程序永远不会跳出。
/**
* @author ChengBing Han
* @date 9:39 2018/6/22
* @description
*/
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
public void run() {
/*
while (!ready){
System.out.println(new Date());
}*/
//这个和上述的优化不同,这个在-server模式下会优化
while (!ready) ;
System.out.println(number);
}
}
public static void main(String[] args) throws InterruptedException {
//永远不会终止程序
new ReaderThread().start();
Thread.sleep(1000);
number = 42;
ready = true;
Thread.sleep(2000);
}
}
备注:上述ready 用volatile 修饰后就会退出,或者用-client 模式启动虚拟机
2.4 分门别类的管理 线程组
2.5 驻守线程的后台:守护线程
2.6 线程优先级:先干重要的事
1-10,优先级逐渐升高
2.7 synchronized(内部锁)
volatile 可以保证原子性,和可见性,但是如果两个线程同时修改了某个变量,那么还是无法识别的,这时volatile的局限性。所以需要synchronized等来确保
2.8 程序中隐蔽的错误
2.8.1 没有提示的错误e
比如两个正数int 相加, 溢出导致 其值为负数。
2.8.2 并发下的ArrayList
两个线程同时对一个ArrayList add 对象,每个线程add 10000 个对象, 最终结果
可能1:ArrayList 中有2万个对象。
可能2:抛出异常
ArrayList 内部结构被破坏了
可能3:ArrayList 中的对象个数小于2万
2.8.3 并发下的HashMap
两个线程同时对HashMap添加对象,每个线程add 10000 个对象,最终结果
可能1:HashMap 中有2万个对象。
可能2:对象个数少于2万
可能3:HashMap内部结构发生破坏,程序无法终止,cpu会被大量消耗。
2.8.4 错误加锁
static Integer i = 0;
.........
synchronized(i){
i++;
}
//问题在于, integer是不可变的,所以每次i++都会创建一个新的对象。可以用javap 反编译查看
允许多个线程同时访问:信号量
允许几个线程访问
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。