Java线程

1.线程和进程
1)进程包含三个特征:独立性,动态性,并发性
2)多线程是扩展了多进程的概念,使得同一个进程可以同时并发处理多个任务
3)一个进程可以拥有多个进程,一个线程必须有一个父进程
归纳:操作系统可以同时执行多个任务,每个任务就是进程,进程可以你同时执行多个任务,每个任务就是进程
2.多线程的优势
1)多线程编程具有如下几个优点
a)进程之间不能共享内存,但线程之间共享内存非常容易。
b)系统穿件进程时需要为该进程重新分配系统资源,但穿件线程则代价小的多,因此使用多线程来实现多个任务并发比多进程效率高
3.线程的创建和启动
1)Thread类代表线程
2)currentThread()是Thread类的静态方法,该方法总是返回当前正在执行的线程对象
3)getName()是Thread类的实例方法,该方法返回调用该该方法的线程名字
4)使用继承Thread类的方法来创建线程类时,多个线程之间无法共享线程类的实例变量
5)实现Runnable接口来创建并启动多线程的步骤:
a)定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体
b)创建Runnable实现类的实例,并以此作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象
6)Runnable对象作为Thread对象的target,Runnable实现类里包括的run(0)方法仅仅作为线程的执行体,而实际的线程对象依然是Thread实例,只是该Thread线程负责执行其target的run()方法
7)Callable接口也是函数式接口
4.线程的三种方式对比
1)采用实现Runnable,Callable接口的方式创建多线程的优缺点:
a)线程类只是实现了Runnable接口或Callable接口,还可以继承其他类
b)多个线程可以共享一个target对象,所以非常适合多个线程来处理同一份资源的情况,从而可以将CPU,代码和数据分开,形成清晰的模型,较好的体现类面向对象的思想
c)劣势是编程稍稍复杂,如果需要访问当前线程,则必须使用Thread。currentThread()方法
2)采用继承Thread类的方式创建线程的优缺点
a)优势是编写简单,如果需要访问当前进程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前进程
b)劣势是因为线程类已经继承了Thread类,所以不能再继承其他父类
鉴于上面分析一般推荐使用Runnable接口,Callable接口的方式来创建多线程
5.线程的生命周期
1)线程被创建并启动后,它既不是一启动就进入了执行状态,也不是一直处于执行状态
2)线程的生命周期:新建(new)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、死亡(Dead)
3)启动线程使用start()方法,而不是run()方法!如果直接调用线程对象的run()方法,系统把线程对象当成一个普通对象,而run()方法也是一个普通方法,而不是线程执行体
4) 如果直接调用线程对象的run()方法,则run()方法里不能直接通过getName()方法来获得当前线程的名字
5)启动线程的正确方法是调用Thread对象的start()方法,而不是直接调用run()方法,否则就变成单线程程序了
6)调用线程的run()方法后,该线程已经不再处于新建状态,不要在次调用线程对象的start()方法
7)调用线程的start()方法之后,该线程立即进入就绪状态,就绪状态相当于“等待执行”,该线程并未真正进入运行状态
6.运行和阻塞状态
1)当发生如下情况是,线程将会进入阻塞状态:
a)线程调用sleep90方法主动放弃所占用的处理器资源
b)线程调用一个阻塞式IO方法,在该方法返回之前,该线程被阻塞
c)线程视图获得一个同步监视器,但该同步监视器正在被其他线程所持有
d)线程正在等待某个通知(notify)
e)程序调用了线程的supend()方法将该线程挂起,但这个方法容易导致死锁
2)针对上面几种情况,当发生如下特定的情况时可以解除上面的阻塞,让该线程重新进入就绪状态
a)调用sleep()方法的线程经过了指定时间
b)线程调用的阻塞式IO方法已经返回
c)线程成功地获得了试图取得的同步监视器
d)线程正在等待某个通知,其他线程发出了一个通知
e)处于挂起状态的线程被调用了resume()回复方法
7.线程死亡
1)run(0方法或call(0方法执行完成,线程正常结束
  线程抛出一个未捕获的Exception或Error
  直接调用该线程的stop()方法来解释该线程,该方法容易导致死锁,通常不推荐使用
2)当主线程结束时,其他线程不受任何影响,并不会随之结束,一但子线程启动起来后,他就拥有和主线程相同的地位,他不会受主线程的影响
3)为了测试某个线程是否已经死亡,可以调用线程对象isAlive()方法,当线程处于就绪,运行,阻塞三种状态时,该方法将返回true;当线程处于新建,死亡两种状态时,该方法将返回false
4)不要试图对一个已经死亡的线程调用start()方法使他重新启动,死亡就是死亡,该线程将不可再次作为线程执行
5)对新建状态的线程两次调用start()方法也是错误的,会引起IllegaThreadStateException异常
8.Join线程
1)join()方法有如下三种重载形式
join():等待被join的线程执行完成
join(long millis):等待被join的线程时间最长为millis毫秒,如果在millis毫秒内被join的线程还没有执行结束,则不再等待
join(long millis,int nanos):等待被join的线程的时间最长为millis毫秒加nanos毫微秒
通常很少用第三种形式
9.后台线程
1)提供服务的线程,如果所有的前台线程都死亡,后台线程会自动死亡
10.线程睡眠:sleep
1)sleep线程有两种重载形式
a)static void sleep(long millis):让当前正在执行的线程暂停millis毫秒,并进入阻塞状态,该方法受到系统计时器和线程调度器的精度与准确度的影响
b)static void sleep(long millis,intnanos):让当前正在执行的线程暂停millis毫秒加nanos毫微秒,并进入阻塞状态,该方法受到系统计时器和线程调度器的精度与准确度的影响
程序很少调用第二种形式的sleep()方法
11.线程让步:yield
1)关于sleep()方法和yield()方法的区别:
a)sleep()方法暂停当前进程后,会给其他线程执行机会,不会理会其他线程的优先级;但yield()方法只会给优先级相同,或优先级更高的线程执行机会
b)sleep()方法会将线程转入阻塞状态,知道经过阻塞时间才回转入就绪状态;而yield()不会将线程转入阻塞状态,它只是强制当前线程进入就绪状态,因此完全有可能某个线程调用yield()方法暂停之后,立即再次获得处理器资源被执行
c)sleep()方法声明抛出InterruptedException异常,所以调用sleep()方法时要么捕捉该异常,要么显式声明抛出该异常,而yield()方法则没有声明抛出任何异常
d)sleep()方法比yield()方法有更好的可移植性,通常不建议使用yield()方法来控制并发线程的执行
12.改变线程的优先级
1)默认情况下,main线程具有普通优先级,由main线程创建的子线程也具有普通优先级
2)MAX_PRIORITY:其值是10
  MIN_PRIORITY:其值是1
  NORM_PRIORITY:其值是5
3)使用setPriority()方法改变线程的优先级
13.同步代码块
1) 当两个进程并发修改同一个文件时就有可能造成异常
2)任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后,该线程会释放对该同步监视器的锁定
3) 通过使用同步的方法可以非常方便的实现线程的安全的类,线程安全的类具有如下特征:
a)该类的对象可以被多个线程安全的访问
b)每个线程调用该对象的任意方法之后都将得到正确结果
c)每个线程调用该对象的任意方法之后,该对象状态依然保持合理状态
d)不可变类总是线程安全的,因为他的对象状态不可改变
4) synchronized关键字可以修饰方法,可以修饰代码块,但不能修饰构造器,成员变量等
5)不要对线程安全类的多有方法都进行同步,只对那些会翻遍竞争资源的方法进行同步
6)如果可变类有两种运行环境:单线程环境和多线程环境,则应该为该可变类提供两种版本,即线程不安全版本和线程安全版本,在单线程环境中使用线程不安全版本以保证性能,在多线程环境中使用线程安全版本









































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值