(转)java多线程的一篇好文
本文只是一些针对初学者或者新手的问题,如果你已经具备良好的基础,那么你可以跳过本文,直接尝试针对进阶水平的Java多线程编程问题及解答。
英文原文:java-success.blogspot,编译:王晓杰
如果你即将去一家从事大型系统研发的公司进行Java面试,不可避免的会有多线程相关的问题。下面是一些针对初学者或者新手的问题,如果你已经具备良好的基础,那么你可以跳过本文,直接尝试针对进阶水平的Java多线程编程问题及解答。
问题:进程和线程的区别
解答:一个进程对应一个程序的执行,而一个线程则是进程执行过程中的一个单独的执行序列,一个进程可以包含多个线程。线程有时候也被称为轻量级进程.
一个Java虚拟机的实例运行在一个单独的进程中,不同的线程共享Java虚拟机进程所属的堆内存。这也是为什么不同的线程可以访问同一个对象。线程彼此共 享堆内存并保有他们自己独自的栈空间。这也是为什么当一个线程调用一个方法时,他的局部变量可以保证线程安全。但堆内存并不是线程安全的,必须通过显示的声明同步来确保线程安全。
问题:列举几种不同的创建线程的方法.
解答:可以通过如下几种方式:
继承Thread 类
实现Runnable 接口
使用Executor framework (这会创建一个线程池)
- classCounter extendsThread {
- //method where the thread execution will start
- publicvoidrun(){
- //logic to execute in a thread
- }
- //let’s see how to start the threads
- publicstaticvoidmain(String[] args){
- Thread t1 = newCounter();
- Thread t2 = newCounter();
- t1.start(); //start the first thread. This calls the run() method.
- t2.start(); //this starts the 2nd thread. This calls the run() method.
- classCounter extendsBase implementsRunnable{
- //method where the thread execution will start
- publicvoidrun(){
- //logic to execute in a thread
- }
- //let us see how to start the threads
- publicstaticvoidmain(String[] args){
- Thread t1 = newThread(newCounter());
- Thread t2 = newThread(newCounter());
- t1.start(); //start the first thread. This calls the run() method.
- t2.start(); //this starts the 2nd thread. This calls the run() method.
通过线程池来创建更有效率。
问题:推荐通过哪种方式创建线程,为什么?
解答:最好使用Runnable接口,这样你的类就不必继承Thread类,不然当你需要多重继承的时候,你将一筹莫展(我们都知道Java中的类只能继承自一个 类,但可以同时实现多个接口)。在上面的例子中,因为我们要继承Base类,所以实现Runnable接口成了显而易见的选择。同时你也要注意到在不同的 例子中,线程是如何启动的。按照面向对象的方法论,你应该只在希望改变父类的行为的时候才去继承他。通过实现Runnable接口来代替继承Thread 类可以告诉使用者Counter是Base类型的一个对象,并会作为线程执行。
问题:简要的说明一下高级线程状态.
解答:下图说明了线程的各种状态.
可执行(Runnable):当调用start()方法后,一个线程变为可执行状态,但是并不意味着他会立刻开始真正地执行。而是被放入线程池,由线程调度器根据线程优先级决定何时挂起执行。
- MyThread aThread = newMyThread();
- aThread.start(); //becomes runnable
执行中(Running):处理器已经在执行线程的代码。他会一直运行直到被阻断,或者通过静态方法Thread.yield()自行放弃执行的机会,考虑到场景切换所带来的开销,yield()方法不应该被经常调用。
等待中(Waiting):线程由于等待I/O等外部进程的处理结果而处于被阻断的状态,调用currObject.wait( )方法会使得当前线程进入等待状态,直到其它线程调用currObject.notify() 或者currObject.notifyAll() 。
睡眠中(Sleeping):重载方法Thread.sleep(milliseconds),Thread.sleep(milliseconds, nanoseconds)可以迫使Java线程进入睡眠状态(挂起)。
由于I/O阻塞(Blocked on I/O):当I/O条件发生变化时(例如读取了几个字节的数据)会迁移到可执行状态。
由于同步阻塞中(Blocked on synchronization): 当获取锁之后会进入执行中状态。
Thread.State 枚举类型包含了Java虚拟机支持的全部的线程状态类型,下面几点Java的线程宗旨确保了这些线程状态成为可能。
对象可以被任何线程共享和修改。
线程调度器的抢占性特性,使得线程可以随时在/不在多核处理之间切换处理器内核,这意味着方法可以在执行的过程中切换状态。否则方法中的死循环将永远阻塞CPU,并且使得不同线程的其他方法始终得不到执行。
为了防止线程安全问题,那些脆弱的方法或者代码块可以被锁定。这使得线程可以处于被锁定或者加锁请求处理中两种状态。
线程在处理I/O资源(如Sockets,文件句柄,数据库连接等)时会进入等待状态,
处于I/O读写中的线程不能被切换,因此他们或者以成功/失败的结果正常完成处理,或者其它线程关闭了相应的资源,迫使他进入死亡或者完成的状态。这也是为什么一个合理的超时时间可以避免线程由于I/O处理而被永远阻塞,从而导致严重的性能问题。
线程可以进入睡眠状态,以使得其他处于等待状态的线程有机会执行。
问题:yield和sleeping有何区别,sleep()和wait()有何区别?
解答:当一个任务调用了yield()方法,它将从执行中状态转变为可执行。而当一个任务调用了sleep(),则将从执行中状态转变为等待中/睡眠中状态。
方法wait(1000)使得当前线程睡眠1秒钟,但调用notify() 或者notifyAll()会随时唤醒线程。而sleep(1000)则会导致当前线程休眠1秒钟。
问题:为什么为了线程安全而锁定一个方法或者一个代码块称为“同步”而不是“锁定”或者“被锁定”
解答:当某个方法或者代码块被声明为”synchronized”后,保存数据的内存空间(例如堆内存)将保持被同步状态。
这意味着:当一个线程获取锁并且执行到已被声明为synchronized的方法或者代码块时,该线程首先从主堆内存空间中读取该锁定对象的所有变化,以确保其在开始执行之前拥有最新的信息。在synchronized部分执行完毕,线程准备释放锁的时候,所有针对被锁定对象的修改都将为写入主堆内存中。这样其他线程在请求锁的时候就可以获取最新的信息。
问题:线程如何进行的同步处理?你可以列举出那些同步级别?同步方法和代码块如何区别?
解答:在Java语言中,每个对象都有一个锁,一个线程可以通过关键字synchronized来申请获取某个对象的锁,关键字synchronized可以被用于方法(粗粒度锁,对性能影响较大)或代码块(细粒度锁)级别。锁定方法往往不是一个很好的选择,取而代之的我们应该只锁定那些访问共享资源的代码块,因 为每一个对象都有一个锁,所以可以通过创建虚拟对象来实现代码块级别的同步,方法块级别的锁比锁定整个方法更有效。
Java虚拟机灵活的使用锁和监视器,一个监视器总体来说就是一个守卫者,他负责确保只有一个线程会在同一时间执行被同步的代码。每个监视器对应一个对象的引用, 在线程执行代码块的第一条指令之前,他必须持有该引用对象的锁,否则他将无法执行这段代码。一旦他获得锁,该线程就可以进入这段受到保护的代码。当线程不 论以何种方式退出代码块时,他都将释放关联对象的锁。对于静态方法,需要请求类级别的锁。
【
(转)java多线程的一篇好文的更多相关文章
- Java多线程系列--“基础篇”05之 线程等待与唤醒
概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long t ...
- Java多线程系列--“基础篇”09之 interrupt()和线程终止方式
概要 本章,会对线程的interrupt()中断和终止方式进行介绍.涉及到的内容包括:1. interrupt()说明2. 终止线程的方式2.1 终止处于“阻塞状态”的线程2.2 终止处于“运行状态” ...
- Java多线程系列--“基础篇”11之 生产消费者问题
概要 本章,会对“生产/消费者问题”进行讨论.涉及到的内容包括:1. 生产/消费者模型2. 生产/消费者实现 转载请注明出处:http://www.cnblogs.com/skywang12345/p ...
- Java多线程系列--“基础篇”04之 synchronized关键字
概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...
- Java多线程系列--“基础篇”02之 常用的实现多线程的两种方式
概要 本章,我们学习“常用的实现多线程的2种方式”:Thread 和 Runnable.之所以说是常用的,是因为通过还可以通过java.util.concurrent包中的线程池来实现多线程.关于线程 ...
- Java多线程系列--“基础篇”03之 Thread中start()和run()的区别
概要 Thread类包含start()和run()方法,它们的区别是什么?本章将对此作出解答.本章内容包括:start() 和 run()的区别说明start() 和 run()的区别示例start( ...
- Java多线程系列--“基础篇”06之 线程让步
概要 本章,会对Thread中的线程让步方法yield()进行介绍.涉及到的内容包括:1. yield()介绍2. yield()示例3. yield() 与 wait()的比较 转载请注明出处:ht ...
- Java多线程系列--“基础篇”07之 线程休眠
概要 本章,会对Thread中sleep()方法进行介绍.涉及到的内容包括:1. sleep()介绍2. sleep()示例3. sleep() 与 wait()的比较 转载请注明出处:http:// ...
- Java多线程系列--“基础篇”08之 join()
概要 本章,会对Thread中join()方法进行介绍.涉及到的内容包括:1. join()介绍2. join()源码分析(基于JDK1.7.0_40)3. join()示例 转载请注明出处:http ...
随机推荐
- Android 读取txt文件并以utf-8格式转换成字符串
博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 博客园: 追风917 # 使用EncodingUtils 今天用到了城市选择三级联动的库,用的这个:https://gi ...
- 为什么每个浏览器都有Mozilla
你是否好奇标识浏览器身份的User-Agent,为什么每个浏览器都有Mozilla字样? Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 ...
- iOS设备、Icon、LaunchImage、图片分辨率
iOS设备 iOS设备的屏幕的大小.分辨率以及比例因数(Scale Factor)[1]. iPhone 设备 宽(inch) 高(inch) 对角线(inch) 逻辑分辨率(point) Scale ...
- C# 之【获取网页响应码200】
做了个监控网站的C#项目,判断网站是否运行正常,采用的就是获取HTTP头返回的状态码. 比如状态码为200的就是网站正常,403是Forbidden,404是网页未找到这样. 代码如下: 首先是使用库 ...
- linux下安装svn(基于编码的方式)
svn是什么,相信能看到这里的同学应该不会有这个问题了,费话不多说,开始: 1.创建目录 mkdir /home/svn/ 2.获取安装svn所需源文件(svn的官方网址是http://subvers ...
- linux系统 web在线日志分析
线上环境出现问题时,不能像本地环境一样,断点查找问题,只有根据日志分析来定位问题,当然有资深的经验也是可以的,哈哈. 最基本的就是cat命令,可以通过cat filename,来查看文件全部内容, & ...
- SGU Volume 1
SGU 解题报告(持续更新中...Ctrl+A可看题目类型): SGU101.Domino(多米诺骨牌)------------★★★type:图 SGU102.Coprimes(互质的数) SGU1 ...
- 博客系统-3.0CodeIgniter系统SAE版本的配置 application/config/
autoload.php(系统启动时自动加载的文件:包,类库,驱动,方法助手,配置) $autoload['libraries'] = array('database', 'access', 'pag ...
- ab基本用法
ab的全称是ApacheBench,是 Apache 附带的一个小工具,专门用于 HTTP Server 的benchmark testing,可以同时模拟多个并发请求.前段时间看到公司的开发人员也在 ...
- Python Standard Library 学习(一) -- Built-in Functions 内建函数
内建函数列表 Built-in Functions abs() divmod() input() open() staticmethod() all() enumerate() int() ord() ...