Java核心API -- 13(线程)

1. 线程相关概念

进程:一个操作系统中可以同时运行多个任务(程序),每个运行的任务(程序)被称为一个进程。

线程:一个程序同时可能运行多个任务(顺序执行流),那么每个任务(顺序执行流)就叫做一个线程。即在进程内部。

并发:线程是并发运行的。操作系统将时间化分为若干个片段(时间片),尽可能的均匀分配给每一个任务,被分配时间片后,任务就有机会被cpu所执行。微观上看,每个任务都是走走停停的。但随着cpu高效的运行,宏观上看所有任务都在运行。这种都运行的现象称之为并发,但不是绝对意义上的“同时发生”。

线程调度:线程调度机制会将所有并发任务做统一的调度工作,划分时间片(可以被cup执行的时间)给每一个任务,时间片尽可能的均匀,但做不到绝对均匀。同样,被分配时间片后,该任务被cpu执行,但调度的过程中不能保证所有任务都是平均的获取时间片的次数。只能做到尽可能平均。这两个都是程序不可控的。

线程的启动和停止:void start():想并发操作不要直接调用run方法!而是调用线程的start()方法启动线程!void stop():不要使用stop()方法来停止线程的运行,这是不安全的操作,想让线程停止,应该通过run方法的执行完毕来进行自然的结束。

2. 线程的创建方式

1)继承自Thread,然后重写run方法:run方法中应该定义我们需要并发执行的任务逻辑代码。



案例29:



2)实现Runnalbe接口。因为有了这样的设计,才有了线程池。

Runnable接口:用于定义线程要执行的任务逻辑。我们定一个类实现Runnable接口,这时我们必须重写run方法,在其中定义我们要执行的逻辑。之后将Runnable交给线程去执行。从而实现了线程与其执行的任务分离开。将任务分别交给不同的线程并发处理,可以使用线程的重载构造方法:Thread(Runnable runnable)。解藕:线程与线程体解藕,即打断依赖关系。



案例30:



3)线程的创建方式三:使用匿名内部类方式创建线程



案例31:



3. 线程的生命周期

线程的生命周期有5种状态:创建(new)、就绪(runnable)、运行(running)、阻塞(block)、死亡(dead)。

4. 线程的常用方法

① static void sleep(times)方法:让当前线程主动进入Block阻塞状态,并在time毫秒后回到Runnalbe状态。 注意事项:使用Thread.sleep()方法阻塞线程时,强制让我们必须捕获“中断异常”。



案例32:



② void interrupt()方法:打断/唤醒线程。一个线程可以提前唤醒另外一个sleep Block的线程。

注意事项:方法中定义的类叫局部内部类:局部内部类中,若想引用当前方法的其他局部变量,那么该变量必须是final的。



案例33:



③ static void yield():当前线程让出处理器(离开Running状态)即放弃当前时间片,主动进入Runnable状态等待。

④ final void setPriority(int):设置线程优先级;优先级越高的线程,理论上获取cpu的次数就越多。但理想与现实是有差距的……设置线程优先级一定要在线程启动前设置!



案例34:



5. wait和notify方法

这两个方法不是在线程Thread中定义的方法,这两个方法定义在Object中。两个方法的作用是用于协调线程工作的。

(1) 等待机制与锁机制密切关联:wait/notify方法必须与synchronized同时使用,谁调用wait或otify方法,就锁谁!

(2) wait()方法:当条将不满足时,则等待。当条件满足时,等待该条件的线程将被唤醒。如:浏览器显示一个图片,displayThread要想显示图片,则必须等代下载线程downloadThread将该图片下载完毕。如果图片没有下杂完成,则dialpayThread可以暂停。当downloadThread下载完成后,再通知displayThread可以显示了,此时displayThread继续执行。

(3) notify()方法:随机通知、唤醒一个在当前对象身上等待的线程。

(4) notifyAll方法:通知、唤醒所有在当前对象身上等待的线程。

6. 守护线程

Daemon后台线程也称为守护线程:当前进程中"所有"、"前台"线程死亡后,后台线程将被强制死亡(非自然死亡),无论是否还在运行。

①守护线程,必须在启动线程前调用。

②main方法也是靠线程运行的,且是一个前台线程。



案例35:



7. 线程的并发安全

多线程在访问同一个数据时(写操作),可能会引发不安全操作。

① 同步异步:

同步:同一时刻只能有一个执行,A和B配合工作,步调一致的处理(B得到A的执行结果才能继续)。如一群人刷卡上公交车。

异步:同一时刻能有多个执行,并发,各自干各自的。如一群人骑自行车。

② synchronized可以修饰方法也可以单独作为语句块存在(同步块)。作用是限制多线程并发时同时访问该作用域。

③ synchronized修饰方法后,会为方法上锁。方法就不是异步的了,而是同步的。锁的是当前对象。

④ synchronized同步块:分析出只有一段代码需要上锁,则使用。效率比直接修饰方法要高。

⑤ 线程安全的效率低,如Vector、Hashtable。线程不安全的效率高,如ArrayList、HashMap 。



案例36:

时间: 2024-10-24 19:06:32

Java核心API -- 13(线程)的相关文章

Java核心API需要掌握的程度

分类: java技术2009-08-29 01:03 213人阅读 评论(0) 收藏 举报 javaapiswingxmlio Java的核心API是非常庞大的,这给开发者来说带来了很大的方便,经常人有评论,java让程序员变傻. 但是一些内容我认为是必须掌握的,否则不可以熟练运用java,也不会使用就很难办了. 1.java.lang包下的80%以上的类的功能的灵活运用. 2.java.util包下的80%以上的类的灵活运用,特别是集合类体系.正规表达式.时间.属性.和Timer. 3.jav

Java核心API -- 2(String、StringBuilder、StringBuffer)

1. String字符串 1)String类型介绍 String类采用final修饰,String对象为不可变对象,一旦在内存中创建,内容不能发生变化,若要对字符串内容改变,那么就会创建新对象. String对象创建,有静态和动态之分. String str1 = "dadsadad"; String str2 = new String("dasdasdadad"); 2)String常量池 JVM对字符串有一个限制,让字符串作为不变对象,这样就可以做到重用.事实上

java核心-多线程(4)-线程类基础知识

1.并发 <1>使用并发的一个重要原因是提高执行效率.由于I/O等情况阻塞,单个任务并不能充分利用CPU时间.所以在单处理器的机器上也应该使用并发. <2>为了实现并发,操作系统层面提供了.但是进程的数量和开销都有限制,并且多个进程之间的数据共享比较麻烦.另一种比较轻量的并发实现是使用线程,一个进程可以包含多个线程.线程在进程中没有数量限制, 数据共享相对简单.线程的支持跟语言是有关系的.Java 语言中支持多线程. <3>Java 中的多线程是抢占式的.这意味着一个任

Java核心API -- 7(Iterator迭代器、Comparable、Comparator比较器)

1. Iterator迭代器 所有Collection的实现类都实现了iterator方法,该方法返回一个Iterator接口类型的对象,用于实现对集合元素迭代的便利.在java.util包下. 1)Iterator定义有三个方法: ①boolean hasNext()方法:判断指针后面是否有元素. ②E next()方法:指针后移,并返回当前元素.E代表泛型,默认为Object类型. ③void remove()方法:在原集合中删除刚刚返回的元素. 2)对于List集合而言,可以通过基于下标的

Java核心API -- 8(Map集合)

1. Map集合 Java.util.Map接口 |--HashMap实现类 |--TreeMap实现类 2. HashMap实现类 Map接口定义的集合又称为查找表,用于存储所谓"Key-Value"键值对.Key可以看成是Value的索引.而往往Key是Value的一部分内容. 1)Key不可以重复,但所保存的Value可以重复. 2)根据内部结构的不同,Map接口有多种实现类,其中常用的有内部为hash表实现的HashMap和内部为排序二叉树实现的TreeMap.同样这样的数据结

Java核心API -- 1(Object类)

1. Object类 在Java体系中,java.lang.Object类位于顶端(是所有对象的直接或间接父类).如果一个类没有写extends关键字声明其父类,则该类默认继承java.lang.Object类.Object类定义了"对象"的基本行为,被子类默认继承. 1)toString方法:返回一个可以表示该对象属性内容的字符串. MyObject obj=new MyObject();    // MyObject类自定义 String info=obj.toString();

Java核心API -- 9(异常)

异常处理 异常结构中的父类Throwable类,其下子类Exceptionlei类和Error类.我们在程序中可以捕获的是Exception的子类异常. Error系统级别的错误:Java运行时环境出现的错误,我们不可控. Exception是程序级别的错误:我们可控. 1)捕获异常两种方式: 一是添加try-catch捕获该异常,二是在我们的方法中声明出也追加这种异常的抛出(继续往外抛). 2)异常处理语句:try-catch,如果try块捕获到异常,则到catch块中处理,否则跳过忽略cat

Java核心API -- 12(对象序列化和反序列化)

1. 对象序列化 将一个对象转换为字节形式的过程就是对象序列化.序列化还有个名称为串行化,序列化后的对象再被反序列化后得到的对象,与之前的对象不再是同一个对象. 1)对象序列化必须实现Serializable接口,但该接口无任何抽象方法,不需要重写方法,只为了标注该类可序列化. 2)且同时建议最好添加版本号(编号随便写):serialVersionUID.版本号,用于匹配当前类与其被反序列化的对象是否处于同样的特征(属性列表一致等).反序列化时,ObjectInputStream会根据被反序列化

Java核心API -- 10(File、RandomAccessFile)

1. File文件类 java使用File类(java.io.File)表示操作系统上文件系统中的文件或目录.换句话说,我们可以使用File操作硬盘上的文件或目录进行创建或删除. File可以描述文件或目录的名字,大小等信息,但不能对文件的内容操作!File类的构造器都是有参的. 1)关于路径的描述:不同的文件系统差异较大,Linux和Windows就不同!最好使用相对路径,不要用绝对路径. 2)"."代表的路径:当前目录(项目所处的目录),在eclipse_workspace/pro