java中的多线程-学习成果标记

这篇文章主要是自己在学习多线程相关知识的时候,在搜索和对比中整理的笔记,方便后期查看。如果有重复,那不是抄袭,是借鉴奥

  • 多线程的概念

1、进程:进程是操作系统中进行保护和资源分配的基本单位,操作系统分配资源以继承为基本单位。每个进程都有独立的代码和数据空间(进程上下文,也叫堆内存),一个进程包含1-N个线程。堆内存在操作系统对进程进行初始化的时候分配,运行过程中也可以向系统申请额外的内存空间,但是记得用完了要还给操作系统,要不然就会发生著名的“内存泄漏”现象。

2、线程:线程是进程的组成部分,它代表了一条顺序的执行流

1)每个线程都有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依赖存在进程中

2)线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源,如程序计数器,一组寄存器和线程栈,但是它可与同属一个进程的其他线程共享进程所拥有的全部资源。

3)多线程可以共享同一段代码

3.并行:操作中系统(也可以说多核CPU)同时执行多个程序,是真正的同时,也就是同一时间。

4.并发:通过CPU调度算法,在用户看来是同时执行,实际上从CPU调度层面不是真正的同时。

5.同步:java中的同步指的是通过人为的控制和调度,保证对于共享资源的多线程访问是线程安全的,来保证结果的准确。通常在代码上加入synchronized关键字来实现同步。

6.线程安全:经常用来描述一段代码的状态。指在并发的情况下,该代码经过多线程使用,线程的调度顺序不影响执行结果。这个时候使用多线程,我们只需要关注系统的内存,CPU是不是够用即可,反过来,线程不安全就意味着线程的调度顺序会影响最终结果。

7.监视器:java会为每个object对象分配一个monitor,当一个线程调用一个对象的同步方法时,JVM会检查该对象的monitor,如果monitor没有被占用,那么这个线程就得到了monitor的占有权,可以继续执行该对象的同步方法;如果monitor被其他等待的线程所占用,那么该线程将被挂起,直到monitor被释放。当线程退出同步方法调用时,该线程会释放monitor,这将允许其他等待的线程获得monitor以使对同步方法的调用执行下去。

8.守护(后台)线程:指为其他线程提供服务线程,比如JVM的垃圾回收线程就是一个守护线程。守护线程会随着主线程的结束而结束。

9.死锁:多个线程同时被阻塞,他们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。

java死锁产生的四个必要条件:

1)互斥使用,即当资源被一个线程使用(占用)时,别的线程不能使用

2)不可抢占,资源请求不能强制从资源占有者手中夺取资源,资源只能有资源占有者主动释放。

3)请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有

4)循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

当上述四个条件都成立的时候,便形成了死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。

解决死锁问题的方法:一种是synchronized,一种是用Lock显示锁实现。

  • 线程状态转换

1)、新建状态(New):新创建了一个线程对象

2)、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

3)、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

4)、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞状态分为三种:

等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中(wait会释放持有的锁)

同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

其他阻塞:运行的线程执行sleep()或join()方法,或者发出I/O请求时,JVM会把该线程置位阻塞状态。当sleep()状态超时、join()等待线程终止或者超时,或者I/O处理完毕时,线程重新转入就绪状态(注意,sleep是不会释放持有的锁)

5)、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

  • 线程常用函数(也可以叫线程调度的方法)

1)、serPriority()和getPriority():Thread类可以设置和获取线程的优先级,Java线程有优先级,优先级高的线程会获得较多的运行机会。

Java线程的优先级用整数表示,取值范围1-10,Thread类有以下三个静态常量:

static int MAX_PRIORITY:线程可以具有的最高优先级,取值为10.

static int MIN_PRIORITY:线程可以具有的最低优先级,取值为1.

static int NORM_PRIORITY:分配给线程的默认优先级,取值为5,主线程默认的优先级

JVM提供了10个线程优先级,但与常见的操作系统都不能很好的映射。如果希望程序能够移植到各个操作系统中,应该仅仅使用Thread类有以下三个静态常量作为优先级,这样能保证同样的优先级采用了同样的调度方式。

2)、sleep(long millis)方法:sleep()使当前线程进入停滞状态(阻塞当前线程),让出CPU的使用,目的是不让当前线程独自霸占该进程所获的CPU资源,以留一定的时间给其他线程执行的机会。在sleep()休眠时间期满后,该线程不一定会立即执行,这是因为其他线程可能正在运行而且没有被调度为放弃执行,除非此线程具有更高的优先级。

sleep()和wait()共同点:

都是在多线程的环境下,都可以在程序的调用出阻塞指定的毫秒数,并返回。

wait()和sleep()都可以通过interrupt()方法,打断线程的暂停状态,从而使线程立刻抛出InterruptedException。

sleep()和wait()不同点:

Thread类的方法:sleep(),yield()等;

Object的方法wait()和notify()等

每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互,来实现线程的同步。sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用

sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

sleep()睡眠时,保持对象锁,仍然占有该锁

wait()睡眠时,释放对象锁。

3)wait(),notify()方法:Object类的wait()方法,对象方法Object.wait()的作用是让需要Obj锁的线程等待,直到其他线程调用Obj的notify()方法或notifyAll()唤醒方法。这两个唤醒方法也是Object类中的方法,行为等价于调用wait(0)一样。

Obj.wait()与Obj.notify()必须要与synchronized(Obj)一起使用,也就是说wait和notify必须是对已经被获取了的Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内,否则会扔出“java.lang.IllegalMonitorStateException”异常。

4)yield()方法:Thread.yield()方法将暂停当前正在执行的线程对象,把CPU占有权让给相同或者更高优先级的线程,但是实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。

5)join()方法:主线程生成并启动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他事务之后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。

6)interrupt()方法:强制中断某个线程,这种结束方式比较粗暴,如果t线程打开了某个资源还没开得及关闭,也就是run方法还没有执行完就强制结束线程,会导致资源无法关闭,所以很少用。

7)currentThread()方法:Thread.currentThread()可以获取当前线程的引用,一般都是在没有线程对象有需要获得线程信息时通过Thread.currentThread()获取当前代码段所在线程的引用。

  • 总结

1、线程同步的目的是为了保护多个线程访问一个资源时对资源的破坏。

2、线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他非同步方法。

3、对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。静态和非静态方法的锁互不干预。一个线程获得锁,在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。
 
4、对于同步,要时刻清醒在哪个对象上同步,这是关键。
 
5、编写线程安全的类,需要时刻注意对多个线程竞争访问资源的逻辑和安全做出正确的判断,对“原子”操作做出分析,并保证原子操作期间别的线程无法访问竞争资源。
 
6、当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。
 
7、死锁是线程间相互等待锁锁造成的,在实际中发生的概率非常的小。真让你写个死锁程序,不一定好使,但是,一旦程序发生死锁,程序将死掉。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值