Java学习笔记之多线程

一、线程和进程的概念和区别

当程序进入内存运行时,即变成一个进程,它是系统进行资源分配和调度的一个独立单位。大部分操作系统都支持多进程并发运行。实际上对一个CPU而言,某个时间点只能执行一个程序,由于轮转时间太快,用户感觉好像是同时进行。

操作系统支持多进程并发,有共用式(主动放弃)和目前常见的抢占式(被动被剥夺)。抢占式即现行进程在运行过程中,如果有重要或紧迫的进程到达(其状态必须为就绪),则现运行进程将被迫放弃挂起,系统将处理机立刻分配给新到达的进程。

线程是进程的组成部分,一个进程可包含多个线程,一个线程必须有一个父进程。线程可以拥有自己的堆栈、计数器和局部变量,但不能拥有系统资源,与父进程的其他线程共享该进程所拥有的全部资源。线程是独立运行的,并不知道其他线程是否存在,它是抢占式的,即当前运行的线程随时可能被挂起,以便另一个线程进行。同一个进程的多个线程可以并发运行。

与进程相比,线程之间隔离程度小,共享内存、文件句柄等,极大提高程序运行效率。当程序创建一个进程时,必须为该系统分配独立的内存空间,并分配大量资源;但创建线程则代价小的多,多线程并发性能比多进程高的多。

二、并发和并行

并行是指同一时刻多条指令在多个处理器上同时进行;并发是指同一时刻只能有一条指令执行,但多个进程指令被快速轮转执行,使得宏观上具有多个进程同时执行的效果。

三、线程的建立和启动

两种方法,继承Thread类或实现Runnable接口。两种方法都是在线程类中实现(重写)run方法作为线程执行的方法,然后在父线程(如main)中用线程对象的start方法进入就绪状态。

四、线程的生命周期

new创建线程对象后,处于新建状态,虚拟机为其分配内存;调用start方法后,进入就绪状态,虚拟机为其创建方法调用栈和程序计数器,但并不意味着开始运行,而是表示可以运行了。至于什么时候运行,取决于JVM调度。注意不要调用对象方法的run方法,否则会被当成是一个普通方法。

当处于就绪状态的线程获得了CPU,则开始执行run方法体,处于运行状态。对于抢占式系统,系统给每个线程一个小时间片处理任务,用完后线程会被剥夺所占用的资源,让其他线程获得执行的机会。

发生以下情况,进入阻塞状态:

1、线程调用sleep主动放弃;

2、线程调用阻塞IO方法(例如输入);

3、试图获得同步监视器,而监视器正被其他线程持有;

4、线程在等待某个通知notify;

相应的相反情况,则阻塞会重新进入就绪状态,注意不是进入运行状态,所以也不保证马上执行。

当run方法执行完,或抛出未捕获的exception或error,线程死亡,可用isAlive判断。

五、线程类的常用方法

join:让一个线程等待另一个线程完成

setDaemon(true):用在start方法之前,设置为后台线程(服务线程,就如JVM垃圾回收线程一样)。如果当所有前台线程都死亡,后台线程会自动死亡。main方法属于前台线程。

sleep:属于静态方法,进入阻塞状态,暂停线程,以毫秒为单位。

yield:静态方法,线程让步,进入就绪状态,即有可能调用后又分到资源立即执行的情况。只有优先级与当前线程相同或比当前线程更高的处于就绪状态的线程才会获得执行机会。

setPriority:设置优先级,优先级高的线程获得较多执行机会。默认和父线程优先级相同,main是普通。优先级为1~10,也有静态变量:

MAX_PRIORITY:10

MIN_PRIORITY:1

NORM_PRIORITY:5

为了更好的移植性,建议用静态变量来设置优先级。

六、线程同步

当多个线程对同一变量进行操作时会引发线程安全问题,run方法本身不具有同步安全性,解决方案:

1、同步代码块:synchronized(obj){...}同步监视器,对obj对象进行锁定。加锁,修改,释放锁。

2、同步方法:synchronized修饰方法,监视调用该方法的对象即this,一般来说更符合面向对象原则。

3、同步锁Lock(略)

死锁:两个线程互相等待对方释放同步监视器会发生死锁,都处于阻塞状态。当系统中出现多个同步监视器的时候容易发生,因为锁只能一次一个。

七、线程通信

wait():线程等待,只有其他线程调用notify()或notifyAll方法才能唤醒;

notify():唤醒再次同步监视器上等待的单个线程。如果所有线程都在此同步监视器上等待,则会选择唤醒其中一个线程,这个选择是任意性的。

notifyAll():唤醒此同步监视器上等待的所有线程。

注意以上三个方法不属于Thread类,属于Object,但是必须在同步监视器对象来调用。

八、线程池

启动一个线程的成本是比较高的,和数据库连接池一样的概念,当需要创建大量生存期很短暂的线程时,更应该考虑线程池使用。启动时线程池创建大量空闲的线程,用完后线程不会死亡,而是返回线程池中成为空闲状态。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值