java-实战java高并发程序设计-ch2java并行程序基础

本文介绍了Java并行编程的基础知识,包括线程的基本操作如新建、终止、中断、等待和唤醒等;探讨了volatile关键字与Java内存模型的关系,并讨论了线程组、守护线程、线程优先级的概念。此外,还分析了并发编程中可能出现的隐蔽错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java并行程序基础

参考:
https://github.com/chengbingh...

2.1 有关线程, 需要知道的事

进程是线程的容器
线程状态图:

clipboard.png
2.2 线程的基本操作
2.2.1新建线程
2.2.2终止线程
stop 暴力终止线程,废弃方法

clipboard.png
clipboard.png

2.2.3线程中断
方法:
clipboard.png

clipboard.png

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方法

clipboard.png

clipboard.png

2.2.6 join 和yeild
join:加入,把线程当做一个方法了。
yeild:让出线程执行权,但是还是会争夺线程的执行权
clipboard.png

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 模式启动虚拟机

clipboard.png

clipboard.png

2.4 分门别类的管理 线程组

2.5 驻守线程的后台:守护线程

2.6 线程优先级:先干重要的事

1-10,优先级逐渐升高

2.7 synchronized(内部锁)
volatile 可以保证原子性,和可见性,但是如果两个线程同时修改了某个变量,那么还是无法识别的,这时volatile的局限性。所以需要synchronized等来确保


clipboard.png

2.8 程序中隐蔽的错误

2.8.1 没有提示的错误e
比如两个正数int 相加, 溢出导致 其值为负数。

2.8.2 并发下的ArrayList
两个线程同时对一个ArrayList add 对象,每个线程add 10000 个对象, 最终结果
可能1:ArrayList 中有2万个对象。
可能2:抛出异常
ArrayList 内部结构被破坏了
clipboard.png
clipboard.png

可能3:ArrayList 中的对象个数小于2万

clipboard.png

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 反编译查看

允许多个线程同时访问:信号量

允许几个线程访问

clipboard.png

clipboard.png

clipboard.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值