慕课网java多线程课程笔记

 

 

第一章 多线程背景知识介绍

进程:
 
 
线程:线程间具有互斥性和同步性
线程是系统中最小的执行单元
同一进程中有多个线程
线程共享进程资源
 
 
 
一般来说,当运行一个应用程序的时候,就启动了一个进程,当然有些会启动多个进程。启动进程的时候,操作系统会为进程分配资源,其中最主要的资源是内存空间,因为程序是在内存中运行的。在进程中,有些程序流程块是可以乱序执行的,并且这个代码块可以同时被多次执行。实际上,这样的代码块就是线程体。线程是进程中乱序执行的代码流程。当多个线程同时运行的时候,这样的执行模式成为并发执行。
在Java程序中,JVM负责线程的调度。线程调度是值按照特定的机制为多个线程分配CPU的使用权。
调度的模式有两种:分时调度和抢占式调度。分时调度是所有线程轮流获得CPU使用权,并平均分配每个线程占用CPU的时间;抢占式调度是根据线程的优先级别来获取CPU的使用权。JVM的线程调度模式采用了抢占式模式。
 

第二章 java线程初体验

 
 
 
Thread.yield(); 可以释放当前线程,并重新开始分配线程的cpu执行权
thread.sleep(),休眠一段时间
thread.join(),让其他线程停止,直到本线程结束。
 
一个class文件中可以有多个类,但是只能有一个public类型的类
同一个时间同一个核只能处理一个线程,只有当线程sleep时CPU才能处理另外一个线程。
 
两种方法实现线程
1、继承 Thread 类
class MyThread extends Thread{};
创建线程:Thread myThread = new MyThread();
启动线程:myThread.start();
2、实现Runnable类                                                         
class MyRunnable implements Runnable{}
创建线程:Thread myRunnable = new Thread(new MyRunnable);
启动线程:myRunnable.start();
3、Thread启动后执行run()方法
4、若实现接口通过Thread.currentThread().getName()方法获取当前线程名称,继承Thread则getName()方法获取当前线程。
 

Thread的构造方法:public Thread(ThreadGroup group,Runable target,String name,Long stackSize)

group指明该线程所属的线程组,target为实际执行线程体的目标对象,name为线程名, stackSize为线程指定的堆栈大小
Runnable接口只有一个方法run(),我们声明类需要实现这个方法
 
vlatile  关键字,保证了线程可以正确的读取其他线程写入的值  ,  如果不写成volatile,由于可见性的问题,当前线程有可能不能读到这个值
//可见性JMM(JAVA内存模型)happens-before原则、可见性原则 ,  用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的值
百度百科volatile的作用是: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
 

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

提醒一下大家:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。

 线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。

在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。

线程的状态

1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
 

第三章 java线程的正确停止

用stop()方法停止JAVA中的线程是不正确的方法。stop方法使得线程戛然而止,完成了什么工作,哪些工作还没有做,都不知道,且清理工作也没有做,所以不是正确的停止线程方法
正确的停止线程方法是,在线程执行中设置状态标识,通过控制标识来控制线程正常完整的执行结束线程
volatile是保证所有子线程里的变量都能同步到主内存里变量的值,

使用volatile 定义boolean running=true,通过设置标志变量running,来结束线程。

通过 while循环中设置的boolean值来判断是否继续
好处:可以完整的完成循环内的操作 保证流程完整性
 

广为流传的错误停止线程的方法:interrupt()
interrupt()--初衷并不是用于停止线程
在调用sleep()或者join()的时候,一旦其他线程调用interrupt(),它将会收到一个异常,这些被阻塞的线程因为某些原因需要被唤醒,比如外部发生了中断而需要响应,这时就采用抛出异常的方式来使其作出响应。总而言之,interrupt()方法并不能正确地停止进程
一个线程在阻塞状态下(例如sleep),此时interrupt的话,将会产生两个结果:
1、进程的interrupt状态被清除(cleard)而非被设置(set)。
2、sleep方法会抛出异常。

 

第四章 线程交互

当多个线程同时共享访问同一数据(内存区域)时,每个线程都尝试操作该数据,从而导致数据被破坏(corrupted),这种现象称为 争用条件
原因是,每个线程在操作数据时,会先将数据初值读【取到自己获得的内存中】,然后在内存中进行运算后,重新赋值到数据。
争用条件 原因: 线程1在还【未重新将值赋回去时】,线程1阻塞,线程2开始访问该数据,然后进行了修改,之后被阻塞的线程1再获得资源,而将之前计算的值覆盖掉线程2所修改的值,就出现了数据丢失情况
 
synchronized 关键字实现互斥行为,既可以出现在方法体之上也可以出现在方法体内,以一种块的形式出现。
然后通过lockObject的wait方法(注意:wait的线程被存放在wait set 中)和notifyAll方法实现同步。
步骤:
1.互斥:同一时间,只能有一个线程访问数据
2.同步:通信机制;一个线程完成,以某种方式通知其他线程
3.锁的概念:private final Object lockObj = new Object();
4.互斥实现方式:synchronized关键字
synchronized(lockObj){---执行代码----}加锁操作
lockObj.wait();线程等待状态,以避免线程持续申请锁,不去竞争cpu资源
lockObj. notify ();唤醒等待队列中第一个等待同一共享资源的线程,进入可运行状态
lockObj.notifyAll();唤醒所有lockObj对象上等待的线程
 
互斥:某一共享数据在同一时间只可以被一条线程访问!通过synchronized关键字实现!
同步:当某些条件满足时,线程通过调用对象监视器的wait(),notify(),notifyAll()方法来实现线程之间的交互!
  
互斥的实现:synchronized(lockObj);java的语法保证的同一时间,只有一个线程获得lockObj
同步:wait(),notify(),notifyall(),都是属于object类,并不是thread类
notify()唤醒wait set中的一条线程,而notifyall()唤醒所有线程
同步是两个线程之间的一种交互的操作(一个线程发出消息另外一个线程响应)。
同步的实现:wait();notify();notifyAll();这三个方法都是Object对象的成员函数。
 
 
 
             
          
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值