23
报报报 报报报 报报 报报报 2014 报 7 报 26 报

厦门大学数据库实验室 JAVA 多线程编程演示

Embed Size (px)

DESCRIPTION

厦门大学数据库实验室 JAVA 多线程编程演示. 报告人:谢荣东 导师:林子雨 2014 年 7 月 26 日. 进程和线程. 进程和线程都是一个控制流程。 一个进程通常对应于一个程序。 一个程序可以由多个不同的线程构成。. 进程. 程序:利用编程语言开发的一个工具软件, 静态的,在没有启动运行之前只是磁盘中的一个普通文件 进程 : 程序启动之后就变成了进程 动态 window 支持多进程,但 cpu 只有一个,所以同一时间只能运行一个进程 动态的 进程相互独立,不共享数据 线程:进程在运行过程中的执行走向,线索 - PowerPoint PPT Presentation

Citation preview

Page 1: 厦门大学数据库实验室 JAVA 多线程编程演示

报告人:谢荣东导师:林子雨2014 年 7 月 26日

Page 2: 厦门大学数据库实验室 JAVA 多线程编程演示

进程和线程都是一个控制流程。一个进程通常对应于一个程序。

一个程序可以由多个不同的线程构成。    

Page 3: 厦门大学数据库实验室 JAVA 多线程编程演示

程序:利用编程语言开发的一个工具软件, 静态的,在没有启动运行之前只是磁盘中的一个普通文件 进程 :程序启动之后就变成了进程 动态

◦ window 支持多进程,但 cpu 只有一个,所以同一时间只能运行一个进程◦ 动态的◦ 进程相互独立,不共享数据

线程:进程在运行过程中的执行走向,线索单线程 : 如果只有一条单一线索 存在的问题 效率相对底下 没有充分合理的利用 cpu多线程 : 多于一条的执行走向线程 共享内存 可以实现多任务

Page 4: 厦门大学数据库实验室 JAVA 多线程编程演示

根据定义,进程为一个数据结构及能在其上进行的一次操作, 它有两个基本特征,

1: 进程是可用于资源的独立单位,2: 进程同时又是一个可独立调度和分派的基本单位,这两个基本属性使之能够独立运行,也能够并发运行。但是在并发运行的时候,系统还需要执行一系列操作:1 、需要创建进程,并为之分配其所必需的资源。2 、撤销进程,对资源进行回收。3 、进程切换,它需要保留当前进程的 CPU 环境和设置新选中进程的 CPU环境。为此需要花费不少处理时间。正因为进程拥有资源,所以在并发执行进程的时候,在创建、撤销和切换,系统需要付出较大的开销,因此,系统中设置的进程不能太多,进程切换的频率也不能过高,这就限制了并发程度的提高。为了解决这一问题,于是产生并引入了线程概念。

Page 5: 厦门大学数据库实验室 JAVA 多线程编程演示

进程:正在进行的程序 我们现在使用的操作系统都是多任务的,即能够 同时 执行多个应用程序。实际是操作系统负责对 CPU 等设备资源进行分配和管理,虽然这些设备某一时刻只能做一件事情,但以非常小的时间间隔交替执行多个程序,就给人同时执行多个程序的感觉。如从 C 盘复制文件到 D 盘的同时从 E盘复制文件到 F盘。

Page 6: 厦门大学数据库实验室 JAVA 多线程编程演示

线程因为具有许多进程所具有的特征,因此被称为 轻量级 进程。计算机科学术语,指运行中程序的调度单位。 线程是进程中的实体,一个进程可以拥有多个线程,一个线程必须有一个父进程。 线程不拥有系统资源,只拥有运行必须的一些数据结构;它与父进程的其它线程共享该进程所拥有的全部资源。 线程可以创建和撤消,从而实现程序的并发执行。 一般,线程具有就绪、阻塞和运行三种基本状态。

Page 7: 厦门大学数据库实验室 JAVA 多线程编程演示

一个进程中可以包含一个或多个线程,一个线程就是程序内部的一条执行线索。 在单线程中,程序代码按调用顺序依次往下执行,不能实现两段程序代码同时交替运行的效果。如果一个程序中要实现两段程序代码同时交替运行,就需要产生多个线程,并指定每个线程上所要运行的程序代码段,这就是多线程。 程序启动运行时,就自动产生了一个线程, main方法就是在这个线程上运行的,当不再产生新的线程时,程序就是单线程。

Page 8: 厦门大学数据库实验室 JAVA 多线程编程演示

多线程在实际工作场景的应用: QQ聊天 (键盘的输入与等待 )、 访问网页 (应用服务器必须能响应多个用户请求 )

创建多线程的方法有 2 种:继承 Thread类实现 Runnable接口

Page 9: 厦门大学数据库实验室 JAVA 多线程编程演示

Java 的线程通过 Thread类来控制,一个 Thread类的对象代表一个线程,而且只能代表一个线程。 通过 Thread类和它定义的对象,我们能获得当前线程对象、获取某一线程的名称、可以实现控制线程暂停一段时间等功能。 每个线程都是通过某个特定 Thread 对象所对应的方法 run( )来完成其操作的,方法 run( ) 称为线程体。 使用 start()方法,线程进入 Runnable(可运行)状态,它将向线程调度器注册这个线程。 调用 start()方法并不一定马上会执行这个线程,正如上面所说,它只是进入 Runnable 而不是 Running 。 注意,不要直接在程序中调用线程的 run()方法。 见 线程图

Page 10: 厦门大学数据库实验室 JAVA 多线程编程演示

就绪Runnable

运行Running

阻塞Blocked

创建new

start()run() 运行完毕线程调度

阻塞事件解除阻塞 dead死亡

Page 11: 厦门大学数据库实验室 JAVA 多线程编程演示

在单线程中, main方法必须等到 run方法返回后才能继续往下执行。

而多线程中,调用 start方法启动线程,运行 run方法后,main方法可以不必等待 run方法返回就继续运行,而另一个线程在一边独自运行,并不影响原来的 main方法的运行。

Page 12: 厦门大学数据库实验室 JAVA 多线程编程演示

1. 要将一段代码放在一个新的线程上运行,该代码所在的类应该继承 Thread 或 实现 Runnable 接口,而需要执行的代码写在 run方法里面。 2. 启动一个线程,不是调用 run方法,而是调用 Thread对象的 start方法。 start方法将产生一个新的线程,并在该线程上运行该 Thread 对象中的 run方法。运行的其实是我们的类 (Thread子类 )的 run方法,多态。 3.run方法执行完后,线程也就结束了,所以,我们可以通过控制 run方法中的循环条件来控制线程的终止。

Page 13: 厦门大学数据库实验室 JAVA 多线程编程演示

public class TestThread { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.setName("myThread");// 设置线程的名称         myThread.start();// 启动线程         for(int i=0;i<100;i++){ //主线程             System.out.println(Thread.currentThread().getName() + “***" + i); } } } class MyThread extends Thread { // 需要在线程中运行的代码写在 run方法中     public void run() { for (int i = 0; i < 100; i++) { //获得当前执行的线程的名称             System.out.println(Thread.currentThread().getName() + "---" + i); } } }

继承 Thread

Page 14: 厦门大学数据库实验室 JAVA 多线程编程演示

通过实现 Runnable接口并实现接口中定义的唯一抽象方法 run() ,可以创建一个线程。

Page 15: 厦门大学数据库实验室 JAVA 多线程编程演示

public class TestRunnable{ public static void main(String[] args){ MyThread2 my = new MyThread2();// 创建一个 Runnable接口实现类        Thread thread = new Thread(my);// 把 my传递给 Thread类        thread.setName(" 线程 -1"); thread.start(); for(int i = 0;i<100;i++){ System.out.println(Thread.currentThread().getName()+"***"+i); } } } class MyThread2 implements Runnable{ //重写 Runnable 中的 run抽象方法,写入需要执行的代码     public void run(){ for(int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+"--"+i); } } }

Page 16: 厦门大学数据库实验室 JAVA 多线程编程演示

与人有生老病死一样,线程也同样要经历新建 (new) 和其它的 Java 对象一样,只分配内存空间和初始化成员变量就绪 (runnable)调用了 start方法后进入就绪状态,什么时候运行取决线程调度器运行 (running)获得了时间片开始执行 run方法体阻塞 (blocked)时间片用完,系统会剥夺其占有的资源,让其他线程有机会执行,优先级高的先执行 死亡 (dead)run方法体执行完,正常结束或抛出 Exception 或 Error 或 调用 stop方

法 (不推荐 )五种状态。

Page 17: 厦门大学数据库实验室 JAVA 多线程编程演示

写一个程序,模拟 4 个售票窗口共同卖 100张火车票的程序。1 :使用继承 Thread类方式实现。2 :使用实现 Runnable接口方式实现。

Page 18: 厦门大学数据库实验室 JAVA 多线程编程演示

继承 Thread, 每个线程卖了 100张票 [没有共享数据 ] public class TicketThread { public static void main(String[] args){ // 执行继承 Thread 的线程         new MyThread().start(); new MyThread().start(); new MyThread().start(); new MyThread().start(); } } class MyThread extends Thread { // 车票数量     private int tickets = 100; public void run() { while (tickets > 0) { System.out.println(this.getName()+"卖出第 ["+(tickets--)+"]张火车票 "); } } }

Page 19: 厦门大学数据库实验室 JAVA 多线程编程演示

实现 Ruaable, 线程总共卖 100张票 [有共享数据 ] public class TicketRunnable { public static void main(String[] args) { // 实现 Runnable接口实现类         myRunnable myR = new myRunnable(); new Thread(myR).start(); new Thread(myR).start(); new Thread(myR).start(); new Thread(myR).start(); } } class myRunnable implements Runnable { //火车票数量     private int tickets = 100; public void run() { while (tickets > 0) {

System.out.println(Thread.currentThread().getName()+"卖出第 ["+(tickets--) +"]张火车票 ."); } } }

Page 20: 厦门大学数据库实验室 JAVA 多线程编程演示

使用 Runnable接口 实际工作中,几乎所有的多线程应用都用实现 Runnable 这种方式。◦ Runnable适合多个相同程序代码的线程去处理同一资源的情况。把虚拟

CPU( 线程 )同程序的代码、数据有效的分离,较好的体现了面向对象的设计思想。◦ 避免由于 Java 的单继承特性带来的局限性。也就是如果新建的类要继承其他类的话 ,因为 JAVA 中不支持多继承 ,就只能实现 java.lang.Runnable接口。◦ 有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。继承 Thread类◦ 不能再继承他类了。◦ 编写简单,可以直接操纵线程,无需使用 Thread.currentThread() 。

Page 21: 厦门大学数据库实验室 JAVA 多线程编程演示

两种实现方式: Thread,Runnable 线程状态:创建线程,就绪 Runnable ,运行 Running ,挂起 Block ,结束 dead 实现 Runnable接口相对于继承 Thread类的好处

Page 22: 厦门大学数据库实验室 JAVA 多线程编程演示
Page 23: 厦门大学数据库实验室 JAVA 多线程编程演示