论坛首页 Java企业应用论坛

一课掌握Java并发编程精髓(完结13章)

浏览 432 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2023-12-20  
一课掌握Java并发编程精髓(完结13章)
网盘地址:https://pan.baidu.com/s/15RSGSAItdF2cqtYVWSexMw 提取码: c5jx
腾讯微云下载地址:https://share.weiyun.com/6RzGbzZc 密码:bi833u


分享一套Java课程——一课掌握Java并发编程精髓(完结13章),附源码+PDF课件下载。

并发编程
1.多线程
       Java 是最先支持多线程的开发的语言之一,Java 从一开始就支持了多线程能力。由于现在的 CPU 已经多是多核处理器了,是可以同时执行多个线程的。

多线程优点
多线程技术使程序的响应速度更快 ,可以在进行其它工作的同时一直处于活动状态,程序性能得到提升。
性能提升的本质 就是榨取硬件的剩余价值(硬件利用率)。

并行与并发
       单核 cpu 下,线程实际是串行执行的。操作系统中有一个组件叫做任务调度器,将 cpu 的时间片,分给不同的线程使用,只是由于 cpu 在线程间(时间片很短)的切换非常快,人类感觉是同时运行的。

       总结为一句话就是:微观串行,宏观并行,一般会将这种线程轮流使用 cpu的做法称为并发,concurrent。

  Java 内存模型(Java Memory Model,JMM)规范了 Java 虚拟机与计算机内存是如何协同工作的。Java 虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为 Java 内存模型。

JVM 主内存与工作内存

       Java 内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。

       这里的工作内存是 JMM 的一个抽象概念,也叫本地内存,其存储了该线程读/写共享变量的副本。

线程常用的方法
start() : 启动当前线程, 调用当前线程的run()方法。
run() : 通常需要重写Thread类中的此方法, 将创建的线程要执行的操作声明在此方法中。
currentThread() : 静态方法, 返回当前代码执行的线程。
getName() : 获取当前线程的名字。
setName() : 设置当前线程的名字。
yield() : 释放当前CPU的执行权。
join() : 在线程a中调用线程b的join(), 此时线程a进入阻塞状态, 知道线程b完全执行完以后, 线程a才结束阻塞状态。
stop() : 已过时. 当执行此方法时,强制结束当前线程.
sleep(long militime) : 让线程睡眠指定的毫秒数,在指定时间内,线程是阻塞状态。
isAlive() :判断当前线程是否存活。

wait()和 sleep()方法有什么区别
sleep 方法和 wait 方法都可以用来放弃 CPU 一定的时间,不同点在于如果线程持有某个对象的监视器,sleep 方法不会放弃这个对象的监视器,wait 方法会放弃这个对象的监视器。
wait需要等待唤醒,而sleep睡眠一定时间之后自动苏醒。

继承Thread类 重写run方法
启动线程是调用start方法,这样会创建一个新的线程,并执行线程的任务。

如果直接调用run方法,这样会让当前线程执行run方法中的业务逻辑。

public class MiTest {

    public static void main(String[] args) {
        MyJob t1 = new MyJob();
        t1.start();
        for (int i = 0; i < 100; i++) {
            System.out.println("main:" + i);
        }
    }

}
class MyJob extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("MyJob:" + i);
        }
    }
}

实现Runnable接口 重写run方法
public class MiTest {

    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread t1 = new Thread(myRunnable);
        t1.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main:" + i);
        }
    }

}

class MyRunnable implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("MyRunnable:" + i);
        }

    }
}

sleep有两个方法重载:

第一个就是native修饰的,让线程转为等待状态的效果
第二个是可以传入毫秒和一个纳秒的方法(如果纳秒值大于等于0.5毫秒,就给休眠的毫秒值+1。如果传入的毫秒值是0,纳秒值不为0,就休眠1毫秒)
sleep会抛出一个InterruptedException

public static void main(String[] args) throws InterruptedException {
    System.out.println(System.currentTimeMillis());
    Thread.sleep(1000);
    System.out.println(System.currentTimeMillis());
}

缓存一致性(MESI)
用于保证多个 CPU cache 之间缓存共享数据的一致

M-modified被修改
该缓存行只被缓存在该 CPU 的缓存中,并且是被修改过的,与主存中数据是不一致的,需在未来某个时间点写回主存,该时间是允许在其他CPU 读取主存中相应的内存之前,当这里的值被写入主存之后,该缓存行状态变为 E
E-exclusive独享
缓存行只被缓存在该 CPU 的缓存中,未被修改过,与主存中数据一致
可在任何时刻当被其他 CPU读取该内存时变成 S 态,被修改时变为 M态
S-shared共享
该缓存行可被多个 CPU 缓存,与主存中数据一致
I-invalid无效

线程安全性
当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的

synchronized 修正计数类方法

修饰类:括号括起来的部分,作用于所有对象
子类继承父类的被 synchronized 修饰方法时,是没有 synchronized 修饰的!!!
Lock: 依赖特殊的 CPU 指令,代码实现



论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics