java线程方面的知识
java中单继承,多实现的:
若为多继承,那么当多个父类中有重复的属性或者方法时,子类的调用结果会含糊不清,因此用了单继承。
为什么是多实现呢?
通过实现接口拓展了类的功能,若实现的多个接口中有重复的方法也没关系,因为实现类中必须重写接口中的方法,所以调用时还是调用的实现类中重写的方法。那么各个接口中重复的变量又是怎么回事呢?
接口中,所有属性都是 static final修饰的,即常量,这个什么意思呢,由于JVM的底层机制,所有static final修饰的变量都在编译时期确定了其值,若在使用时,两个相同的常量值不同,在编译时期就不能通过。
一、进程和线程的基础知识
1、进程和线程的概念
进程:运行中的应用程序称为进程,拥有系统资源(cpu、内存)
线程:进程中的一段代码,一个进程中可以有多段代码。本身不拥有资源(共享所在进程的资源)
在Java中,程序入口被自动创建为主线程,在主线程中可以创建多个子线程。
区别:
1、是否占有资源问题
2、创建或撤销一个进程所需要的开销比创建或撤销一个线程所需要的开销大。
3、进程为重量级组件,线程为轻量级组件
多进程: 在操作系统中能同时运行多个任务(程序)
多线程: 在同一应用程序中有多个功能流同时执行
2、线程的主要特点
①、不能以一个文件名的方式独立存在在磁盘中;
②、不能单独执行,只有在进程启动后才可启动;
③、线程可以共享进程相同的内存(代码与数据)。
3、线程的主要用途
①、利用它可以完成重复性的工作(如实现动画、声音等的播放)。
②、从事一次性较费时的初始化工作(如网络连接、声音数据文件的加载)。
③、并发执行的运行效果(一个进程多个线程)以实现更复杂的功能
4、多线程(多个线程同时运行)程序的主要优点
①、可以减轻系统性能方面的瓶颈,因为可以并行操作;
②、提高CPU的处理器的效率,在多线程中,通过优先级管理,可以使重要的程序优先操作,提高了任务管理的灵活性;另一方面,在多CPU系统中,可以把不同的线程在不同的CPU中执行,真正做到同时处理多任务。
java中创建一个线程有两种方式:
1、继承Thread类,重写run()方法,然后直接new这个对象的实例,创建一个线程的实例。然后调用start()方法启动线程
2、实现Runnable接口,重写run()方法,然后调用new Thread(runnable)的方式创建一个线程,然后调用start()方法启动线程
注意:
①、在继承Thread的方式中,可以使用getName()方法,来获得当前线程的名字,这是因为在Thread类中,有这个方法。可是在实现Runnable方式中,却不可以使用this.getName(),因为Runnable接口没有这个方法(可以看出来,因为我们没有提示我们需要重写这个方法),所以只能通过Thread的静态方法Thread.currentThread()取得当前的Thread对象,在调用getName()方法,来取得当前线程的名字。
②、对Java来说,run()方法没有任何特别之处。像main()方法一样,它只是新线程知道调用的方法名称(和签名)。因此,在Runnable上或者Thread上调用run方法是合法的。但并不启动新的线程。只有调用start()方法才会启动新线程。
3、两种方式的对比
采用实现Runnable接口方式的多线程具有优势,一般都会使用这种方式:
1、线程类只是实现了Runnable接口,还可以继承其他类。
2、在这种方式下,可以多个线程共享一个Runnable target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好的体现了面向对象的思想。
notice: yeild和sleep不会释放锁,wait会释放锁.
线程的生命周期和状态控制:
说明:destory stop 暴力停止线程的方法不安全 ,destory停止线程的时候不会释放线程的所有资源锁,其他的线程依旧阻塞,如果有一个线程想要获取该锁,就会死锁。stop()方法会强制释放所有的锁,使得程序继续运行,但是不安全。
suspend被弃用的原因是因为它会造成死锁。suspend方法和stop方法不一样,它不会破换对象和强制释放锁,相反它会一直保持对锁的占有,一直到其他的线程调用resume方法,它才能继续向下执行。
假如有A,B两个线程,A线程在获得某个锁之后被suspend阻塞,这时A不能继续执行,线程B在或者相同的锁之后才能调用resume方法将A唤醒,但是此时的锁被A占有,B不能继续执行,也就不能及时的唤醒A,此时A,B两个线程都不能继续向下执行而形成了死锁。这就是suspend被弃用的原因。
如何正确的终止一个线程:可以在主线程中设置一个flag值,将flag置为false,即可停止子线程的运行.
线程的sleep方法和线程的yield方法区别:
① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
④ sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性.
原因:如果是实例方法,就可以实现在一个线程里随时让其它线程在执行中休眠,而且这种休眠是不放弃锁的。那么这种简单粗暴就很容易引起混乱,因此目前这种机制其实就是一种限制:你可以选择给自己吃安眠药,而不能随便给正在工作的别人吃安眠药。
http://www.cnblogs.com/tk55/p/6875503.html
http://blog.csdn.net/lonelyroamer/article/details/7949969
Thread_wait、notify、notifyAll的使用方法
wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。
这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。
•如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
•如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
•如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
其中wait方法有三个over load方法:
wait()
wait(long)
wait(long,int)
wait方法通过参数可以指定等待的时长。如果没有指定参数,默认一直等待直到被通知。
另外补充一些摘至其他博客的文章:
在多线程的情况下,由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。
wait与notify是java同步机制中重要的组成部分。结合与synchronized关键字使用,可以建立很多优秀的同步模型。
synchronized(this){ }等价于publicsynchronized void method(){.....}
同步分为类级别和对象级别,分别对应着类锁和对象锁。类锁是每个类只有一个,如果static的方法被synchronized关键字修饰,则在这个方法被执行前必须获得类锁;对象锁类同。
首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){......}的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错:
java.lang.IllegalMonitorStateException:current thread not owner
在调用wait的时候,线程自动释放其占有的对象锁,同时不会去申请对象锁。当线程被唤醒的时候,它才再次获得了去获得对象锁的权利。
所以,notify与notifyAll没有太多的区别,只是notify仅唤醒一个线程并允许它去获得锁,notifyAll是唤醒所有等待这个对象的线程并允许它们去获得对象锁,只要是在synchronied块中的代码,没有对象锁是寸步难行的。其实唤醒一个线程就是重新允许这个线程去获得对象锁并向下运行。
notifyAll,虽然是对每个wait的对象都调用一次notify,但是这个还是有顺序的,每个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。其实启动等待对象链中各个线程的也是一个线程,在具体应用的时候,需要注意一下。
wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能。因为都个对像都有锁,锁是每个对像的基础,当然操作锁的方法也是最基础了。
wait():
等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则编译可以通过,但运行时会收到一个异常:IllegalMonitorStateException。
调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。
notify():
唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
调用任意对象的notify()方法则导致因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。
notifyAll():
唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。
通常,多线程之间需要协调工作:如果条件不满足,则等待;当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制的实现依赖于wait/notify。等待机制与锁机制是密切关联的。
例如:
synchronized(obj) {
while(!condition) {
obj.wait();
}
obj.doSomething();
}
当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。
在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A :
synchronized(obj) {
condition = true;
obj.notify();
}
需要注意的概念是:
# 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj){...} 代码段内。
# 调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj){...} 代码段内唤醒A。
# 当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。
#如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。
#obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。
# 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。
谈一下synchronized和wait()、notify()等的关系:
1.有synchronized的地方不一定有wait,notify
2.有wait,notify的地方必有synchronized.这是因为wait和notify不是属于线程类,而是每一个对象都具有的方法,而且,这两个方法都和对象锁有关,有锁的地方,必有synchronized。
另外,注意一点:如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,该线程就已经不是currentthread了。
java线程方面的知识的更多相关文章
- Java线程并发控制基础知识
微博上众神推荐今年4月刚刚出版的一本书,淘宝华黎撰写的<大型网站系统与Java中间件实践>,一线工程师的作品,实践出真知,果断要看. 前两章与<淘宝技术这十年>内容类似,基本是 ...
- java线程基础知识----线程与锁
我们上一章已经谈到java线程的基础知识,我们学习了Thread的基础知识,今天我们开始学习java线程和锁. 1. 首先我们应该了解一下Object类的一些性质以其方法,首先我们知道Object类的 ...
- 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型
关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...
- java线程基础知识----线程基础知识
不知道从什么时候开始,学习知识变成了一个短期记忆的过程,总是容易忘记自己当初学懂的知识(fuck!),不知道是自己没有经常使用还是当初理解的不够深入.今天准备再对java的线程进行一下系统的学习,希望 ...
- java线程基础知识----java daemon线程
java线程是一个运用很广泛的重点知识,我们很有必要了解java的daemon线程. 1.首先我们必须清楚的认识到java的线程分为两类: 用户线程和daemon线程 A. 用户线程: 用户线程可以简 ...
- Java并发(基础知识)—— Executor框架及线程池
在Java并发(基础知识)—— 创建.运行以及停止一个线程中讲解了两种创建线程的方式:直接继承Thread类以及实现Runnable接口并赋给Thread,这两种创建线程的方式在线程比较少的时候是没有 ...
- Java线程知识
概念 线程生命周期 Java线程模型 线程方法 线程优先级 线程同步 线程在多任务处理应用程序中有着至关重要的作用 概念 基本概念 进程:在操作系统中每个独立运行的程序就是一个进程 线程:程序执行的一 ...
- [不得不知道系列]Java线程面试你不得不知道的基础知识一
Java内存管理面试指南一 Java基础面试指南一 Java基础面试指南二 Java基础面试指南三 Java基础面试指南四 Java线程面试指南一 Java线程面试指南二 Redis面试指南一 Kaf ...
- Java线程知识拾遗
知识回顾 进程与线程是常常被提到的两个概念.进程拥有独立的代码段.数据空间,线程共享代码段和数据空间,但有独立的栈空间.线程是操作系统调度的最小单位,通常一个进程会包含一个或多个线程.多线程和多进程都 ...
随机推荐
- GitHub Pages站点官方宣布开始使用HTTPS
导读 数百万人依靠GitHub Pages,将其作为他们的网站主机,除此之外,还有数百万人每天访问这些网站.为了更好地保护到GitHub Pages站点的通讯,也为了鼓励在因特网上更广泛地采用HTTP ...
- 后端UI框架
BootStrap EasyUI DWZ ExtJS
- js对用户信息加密传输 java后端解密
1.加密采用服务端随机生成加密因子放入session中,传入登录或注册界面(每次进入都刷新) 2.页面中引入jquery.aes.js(这个js从网上下的坑比较多,引入先后顺序不一致都会报错,所以最后 ...
- Oracle Schema Objects(Schema Object Storage And Type)
One characteristic of an RDBMS is the independence of physical data storage from logical data struct ...
- UITextView 的 return响应事件
在UITextView里没有UITextField里的- (BOOL)textFieldShouldReturn:(UITextField *)textField;直接的响应事件;那么在TextVie ...
- 修改Android模拟器的system分区,以及加入SuperSU
http://www.claudxiao.net/2013/10/persistent-change-emulator-system-partition/ 对Android的模拟器,如果要修改其s ...
- libxml_disable_entity_loader
w避免加载外部实体字符. http://php.net/manual/en/function.libxml-disable-entity-loader.php libxml_disable_entit ...
- 常用移动web开发框架--转载
阅读目录 1.1 jQuery mobile flat-ui 主题 1.2jQuery mobile Bootstrap 主题 4.1 GMU 4.2 Clouda+ 4.3 efe 5.1 Sp ...
- React中ref的用法
在React数据流中,父子组件唯一的通信方式是通过props属性:那么如果有些场景需要获取某一个真实的DOM元素来交互,这时候就要用到React的refs属性. 1.可以给DOM元素添加ref属性 c ...
- 前端开发 - jsBom
一.jsBom简介 jsBom = javascript browser object modelBOM指的是浏览器对象模型 Browser Object Model,它的核心就是浏览器. 二.Bom ...