Java线程编程基础 第一章
1、本章任务:建立多线程程序
2、本章知识点:
- 了解Java线程模型
- 掌握创建线程的方法
- 设置线程优先级
3、多线程编程概述
- Java提供了对多线程编程的内置支持
- 多线程程序包括能够并发运行的两个或多个代码段
单线程、多线程对比示例图:
从图中可以看出:
1.单线程中的3段代码只能在不同的时间点执行,
2.多线程中的3段代码可以在同一时间点执行
4、进程与线程
- 进程:一个进程是 一个正在执行的程序 ,目前的操作系统大多都支持同时运行两个或多个程序,称为多任务操作系统
- 线程:单个程序 可以同时执行 两个或更多的任务 ,每个任务称为 一个线程 ,进程包含线程
- 进程是重量级的任务 ,每个进程都有自己独立的地址空间
- 线程是轻量级的任务 ,他们共享一个地址空间,共享同一个进程
- 进程间通信代价昂贵而且受限,线程通信很容易
- 利用多线程可使你的程序最大限度地利用CPU,因为空闲时间被限制在最小
5、 Thread类和Runnable接口
Java的多线程系统构建在Thread类 、方法以及Runnable接口 之上。
可以通过继承Thread类或者实现Runnable接口创建一个新线程
Thread类定义了几个管理线程的方法,常用方法如下:
方法名 功能
====================================
getName 获取线程名
getPriority 获得线程的优先级
isAlive 判定线程是否仍在运行
join 等待一个线程终止
run 线程入口方法
sleep 暂停一个线程一段时间
start 启动线程
6、程序的主线程
6.1)主线程描述
Java程序启动时 (从main方法开始),一个线程 立刻开始运行,这个线程称
为主线程 ,主线程的重要性体现在如下两个方面:
1)它是产生其他子线程的线程
2)一般情况下,必须是最后一个结束 执行的线程,
因为它要执行各种关闭操作
主线程不但在程序开始时自动创建,也能通过Thread对象来控制,此时需要
调用:Thread.currentThread()
6.2)主线程控制示例代码
public static void main(String args[ ]){ Thread t = Thread.currentThread( ); //获取当前线程(主线程) System.out.println("当前线程:" + t); //输出:线程名-优先级-线程组名 //改变主线程名称 t.setName("My Thread"); System.out.println("改变之后的名称:" + t); //打印数字1 ~ 5,每隔1秒打印1次 try{ for(int i = 1; i <= 5; i++){ System.out.println(i); Thread.sleep(1000); //休眠1000毫秒 } }catch(InterruptedException e){ System.out.println( " 主线程中断! " ); } }
7、创建线程
Java定义了两种 创建线程的方法 :
1)可以实现Runnable接口 ,这是创建线程最简单的方法,实现Runnable接口
只需一个简单的run()方法,其声明如下:
public void run();
run()方法是线程的进入点,线程在run方法返回时结束
2)可以继承Thread类 ,重写Thread类的run()方法
8、创建线程 方法1:实现Runnable接口
/** * 线程类MyThread,实现Runnable接口 */ public class MyThread implements Runnable{ //线程类 //线程入口点 public void run(){ try{ //打印数字1 ~ 5,每隔500毫秒打印一次 for(int i = 1; i <= 5; i++){ System.out.println("子线程打印:" + i); Thread.sleep(500); //休眠500毫秒 } }catch(InterruptedException e){ System.out.println("子线程中断!"); } System.out.println("子线程执行结束!"); } } /** * 线程类MyThread的测试类 */ public class TestMyThread{ public static void main(String args[ ]){ //创建线程 Thread t = new Thread(new MyThread(), "Demo Thread"); System.out.println("子线程被创建:" + t); //显示线程信息 t.start(); //启动线程 //主线程中间隔1秒,打印数字1 ~ 5 try{ for(int i = 1; i <= 5; i++){ System.out.println("主线程打印:" + i); Thread.sleep(1000); //休眠1000毫秒 } }catch(InterruptedException e){ System.out.println("主线程中断!"); } System.out.println("主线程执行结束!"); } }
9、创建线程 方法2:继承Thread类
/** * 线程类MyThread1,继承Thread类 */ public class MyThread1 extends Thread{ public MyThread1(){ super("Demo Thread"); //线程命名 } //重写线程入口方法 public void run(){ try{ //打印数字1 ~ 5,每隔500毫秒打印一次 for(int i = 1; i <= 5; i++){ System.out.println("子线程打印:" + i); Thread.sleep(500); //休眠500毫秒 } }catch(InterruptedException e){ System.out.println("子线程中断!"); } System.out.println("子线程执行结束!"); } } /** * 线程类MyThread1的测试类 */ public class TestMyThread1{ public static void main(String args[ ]){ //创建线程 Thread t = new MyThread1(); System.out.println("子线程被创建:" + t); //显示线程信息 t.start(); //启动线程 //主线程中间隔1秒,打印数字1 ~ 5 try{ for(int i = 1; i <= 5; i++){ System.out.println("主线程打印:" + i); Thread.sleep(1000); //休眠1000毫秒 } }catch(InterruptedException e){ System.out.println("主线程中断!"); } System.out.println("主线程执行结束!"); } }
10、如何选择创建线程的方式
问: Java有两种创建线程的方式,哪种更好?
1. Thread类定义了多个派生类可以重写的方法,run()方法只是其中之一,
所以只有在需要增强或者修改Thread类时才应该使用继承Thread类方式
2. 如果不想重写Thread类的run()方法外的其他方法,最好还是简单的
实现Runnable接口(推荐)
11、线程的状态
- 准备运行状态:ready to run
- 运行状态:running
- 暂停状态:suspended 运行中的线程可以暂停,暂停的线程可以重新启动
- 阻塞状态:blocked 线程在等待其他资源时被阻塞
(这个状态和视频播放器的操作非常类似,: )
注意:线程在任何时候都能被终止,一旦终止就不能被重新激活
12、启动多个线程
/** * 改进的MyThread线程类(改为自启动线程) */ public class MyThread implements Runnable { private Thread t;//线程对象 public Thread getT() { return t; } /**构造方法*/ public MyThread(String threadName){ //创建线程对象 this.t = new Thread(this, threadName); System.out.println("创建子线程:" + threadName); //启动线程 this.t.start(); } /** * 功能:线程入口方法 */ public void run() { Thread t = Thread.currentThread(); try { //打印数字1 ~ 5,间隔1秒 for(int i = 1; i <= 5; i++){ System.out.println(t.getName() + " 打印:" + i); //休眠1秒 Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println("子线程中断!"); } System.out.println("子线程结束!"); } } /** * 多线程测试类 */ public class TestMyThread { public static void main(String[] args) { //创建线程对象1 MyThread t1 = new MyThread("子线程1"); //创建线程对象2 MyThread t2 = new MyThread("子线程2"); try { //主线程打印数字1 ~ 5,间隔1秒 for(int i = 1; i <= 5; i++){ System.out.println("主线程打印:" + i); //休眠1秒 Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println("主线程中断!"); } System.out.println("主线程结束!"); } }
13、使用isAlive() 和join()
问题: 主线程一般要最后结束,之前的示例中是通过在main方法中加入sleep()
使主线程休眠足够长的时间以确保主线程最后结束,这个解决方式合理吗?怎样
才能知道子线程是否终止?或者说怎样才能保证主线程最后结束?
答案: 有两种方式可以确定一个线程是否结束:
1)在线程中调用isAlive(),这个方法由Thread定义,如果它调用的线程仍在运行,
返回true,否则返回false
2)使用join()方法来等待另一个线程的结束,该方法一直等待直到它调用的线程终止
14、isAlive()和jion()示例
尝试运行以下代码并观察主线程是否最后结束:
public static void main(String[] args) { MyThread t1 = new MyThread("子线程1"); // 创建线程1 MyThread t2 = new MyThread("子线程2"); // 创建线程2 MyThread t3 = new MyThread("子线程3"); // 创建线程3 //显示线程是否运行 System.out.println("子线程1是否运行:" + t1.getT().isAlive()); System.out.println("子线程2是否运行:" + t2.getT().isAlive()); System.out.println("子线程3是否运行:" + t3.getT().isAlive()); // 主线程等待子线程结束 try { System.out.println("等待子线程结束…"); t1.getT().join(); // 等待t1线程结束 t2.getT().join(); // 等待t2线程结束 t3.getT().join(); // 等待t3线程结束 } catch (InterruptedException e) { System.out.println("主线程中断!"); } //显示线程是否运行 System.out.println("子线程1是否运行:" + t1.getT().isAlive()); System.out.println("子线程2是否运行:" + t2.getT().isAlive()); System.out.println("子线程3是否运行:" + t3.getT().isAlive()); System.out.println("主线程执行结束!"); }
15、线程优先级概述
Java给每个线程分配一个优先级,以决定哪个线程可以优先分配CPU时间
优先级是一个整数,用于指定线程的相对优先程度
优先级可以决定什么时候从一个运行中的线程切换到另一个线程,切换规则如下:
- 一个线程自愿释放控制(放弃、睡眠或者阻塞),所有其他线
程被检查,高优先级线程被分配CPU时间 - 一个线程可以被另一个高优先级线程抢占资源,称为抢占式多任务
注意:具有同一优先级的线程竞争CPU时间,不同操作系统的处理方式上存在差别
16、线程优先级设置
- 线程调度器使用线程优先级以决定什么时候允许运行
- 理论上高优先级的线程将比低优先级的线程得到更多CPU时间
- 低优先级线程在运行时,高优先级的线程会抢占低优先级线程的执行权
-
设置线程优先级,使用setPriority()方法:
final void setPriority(int level);
参数level为线程的优先级 ,其值在1 ~ 10 之间
Thread类提供了如下常量方便优先级的设置
Thread.MIN_PRIORITY == 1
Thread.MAX_PRIORITY == 10
Thread.NORM_PRIORITY == 5
17、线程优先级示例
/** * 功能:计数器线程 */ public class Clicker implements Runnable { private int click = 0;//计数值 private Thread t;//线程对象 private volatile boolean running = true;//运行开关 public int getClick() { return click; } public Thread getT() { return t; } /**构造方法,参数为优先级*/ public Clicker(int priority){ this.t = new Thread(this); this.t.setPriority(priority);//设置线程优先级 } public void run() { while(this.running){ this.click++;//计数器累加 } } public void start(){ this.t.start();//启动线程 } public void stop(){ this.running = false;//结束线程 } } /** * 计数器线程测试类 */ public class TestClicker { public static void main(String[] args) { //创建线程,设置4种档次的优先级 Clicker hi = new Clicker(Thread.NORM_PRIORITY + 2); Clicker hi1 = new Clicker(Thread.NORM_PRIORITY + 4); Clicker lo = new Clicker(Thread.NORM_PRIORITY - 2); Clicker lo1 = new Clicker(Thread.NORM_PRIORITY - 4); //启动线程 hi.start(); hi1.start(); lo.start(); lo1.start(); try { Thread.sleep(2000);//休眠2秒 //结束线程 hi.stop(); hi1.stop(); lo.stop(); lo1.stop(); //等待线程结束 hi.getT().join(); hi1.getT().join(); lo.getT().join(); lo1.getT().join(); } catch (InterruptedException e) { System.out.println("主线程中断!"); } //显示计数器值 System.out.println("lo1计数器:" + lo1.getClick()); System.out.println("lo计数器:" + lo.getClick()); System.out.println("hi计数器:" + hi.getClick()); System.out.println("hi1计数器:" + hi1.getClick()); System.out.println("主线程结束!"); } }
18、总结
- 进程与线程的区别?
- 如何获取主线程?
- 创建线程的两种方式?
- 获知线程是否运行使用哪个方法?
- 等待线程执行结束使用哪个方法?
- 线程优先级的范围是什么?
相关推荐
完整版java基础入门教程由浅入深讲解 Java语言编程基础 第13章 多线程(共50页).ppt 完整版java基础入门教程由浅入深讲解 Java语言编程基础 第14章 网络通信(共76页).ppt 完整版java基础入门教程由浅入深讲解 ...
电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关...第五章 Java线程编程的例子 第六章 Java线程调度 第七章 Java线程调度例子 第八章 和同步相关的高级主题 第九章 多处理器机器上的并行化 第十章 线程组
在本章中,我们探讨了多线程编程的基础知识,包括进程和线程的概念、Java对多线程的支持、第一个多线程程序等。下一章,我们将深入探讨多线程编程的高级技术和实践经验。 多线程编程的应用 多线程编程广泛应用于...
在第一章Java编程简介中,我们学习了Java语言的历史和特点,了解到Java是由Sun公司的James Gosling等人在1990年代初期开发的,最初命名为Oak。随着互联网的发展,Java逐渐转向Web应用程序,并在1995年正式发布。Java...
第一章“基本网络概念”主要介绍了网络的基础知识,包括TCP/IP协议族、互联网的工作原理、IP地址和域名系统。这一章将引导读者理解网络通信的基本模型,为后续的网络编程打下坚实的基础。作者深入浅出地解释了网络...
《Java2.0网络多线程编程实例教程》是一本由李荣贵等人编写的书籍,专注于Java2.0(即Java SE 2)平台下的网络编程和多线程技术。该书通过丰富的实例,旨在帮助读者深入理解和掌握这两项核心的Java开发技能。 在...
Java多线程编程是Java高级应用的重要...总之,Java的多线程编程涉及到的内容广泛,从基础的线程创建到复杂的同步策略,都需要深入理解和实践才能熟练掌握。通过学习这一章,开发者可以更好地设计和实现高效的并发程序。
### Java语言基础入门教程:第14章 线程 #### 课程概述 本章节主要介绍了Java中的线程概念及其实现方式。通过学习,读者可以了解到如何创建线程、理解多线程的基本原理以及如何控制线程的运行。 #### 1. 线程与多...
Java 基础入门第三版第一章作业 Java 是一种高级语言,它具有跨平台性、面向对象、简单等特点。Java 语言的基本结构由类、对象、继承、多态、封装等概念组成。在 Java 中,类是最小的程序单元,用于定义对象的行为...
第一章 线程简介 Java术语 线程概述 为什么要使用线程? 总结 第二章 Java线程API 通过Thread类创建线程 使用Runable接口的线程 线程的生命周期 线程命名 访问线程 线程的启动、停止和连接 总结 第三章 同步技术...
Thinking in Java 自学笔记——第一章 对象导论 本章节总结了面向对象程序设计(Object-oriented Programming, OOP)的基本概念和原则,以帮助读者更好地理解 Java 编程语言。以下是对标题、描述、标签和部分内容的...
在这个Java编程基础课件中,我们将会探讨一系列关键知识点,包括Java语言的起源、特性、环境搭建,以及基本语法元素。 首先,Java起源于1995年,由Sun Microsystems的詹姆斯·高斯林(James Gosling)等人设计,现...
Java编程基础是学习Java开发的重要基石,而"张孝祥java就业培训教程第二章_Java 编程基础WORD版"正是这样一个专注于此领域的教程。张孝祥,作为一位知名的IT教育专家,他的教程通常深入浅出,适合初学者入门及进阶者...
第一章介绍了Java的基础概念,如对象、面向对象、javac编译器、JVM以及JRE的作用。第二章讲解了Java编程基础,包括关键字(如"class")、注释类型(单行、多行和文档注释)、数据类型(如基本数据类型和引用数据类型...
1 第一章 Java语言概述(1) 2 第一章 Java语言概述(2) 3 第二章 Java基础 4 第三章 面向对象程序设计基础 5 第四章 图形用户界面设计 6 第五章 Java Swing基础 7 第六章 Java图形与图像处理 8 第七章 多线程与...
Java 实用教程的第一章主要介绍了Java语言的基本概况,包括其诞生背景、学习的重要性、语言特点、与C/C++的关系以及Java的运行平台。这一章的知识点涵盖了Java的基础和核心概念,对于初学者来说是非常关键的。 1. *...
虽然这里只提供了第一章的内容,但这一章通常会涵盖基础理论和核心概念,对于初学者来说是非常宝贵的入门资料。 Java并发编程的核心在于理解线程的概念,线程是程序执行的最小单元,每个线程都有自己的程序计数器、...
本教程的第一章将对Java语言进行概览,帮助初学者建立坚实的基础。 一、Java语言的特性 1. 面向对象:Java是一种面向对象的语言,支持类、对象、继承、封装和多态等概念,使得代码结构清晰,易于维护。 2. 可移植性...
这一章还可能涉及编写第一个"Hello, World!"程序,以及对变量、数据类型、运算符和控制流的基本介绍。 2. **Chapter03.pdf**:可能会深入讲解面向对象编程(OOP)概念,如类、对象、封装、继承和多态性。此外,还将...