笔记汇总:《Java面向对象程序设计》学习笔记
# 第 15 章 Java 多线程机制
Java 语言的一大特点就是内置了对多线程的支持。
多线程是指同时存在几个执行体,按几条不同的执行线索共同工作的情况。
我们感觉线程正在同步执行,但并不是真的同时执行多个线程,只是Java 快速地从一个线程切换到另一个线程。
Java 虚拟机( JVM )负责管理线程。
程序
进程
进程是程序的一次动态执行过程。
os 可以管理多个进程,即让多个进程都机会使用系统的资源,比如 CPU 资源。
(一个 OS 里可以多个进程)
线程
其他
Java 语言使用 Thread 类及其子类的对象来表示线程。
使用 Thread 类及其子类的对象来表示线程。
Thread 提供 getstate() 方法返回枚举类型 Thread.State 的下列枚举常量之一:
NEW , RUNNABLE , BLOCKED , WAITING , TIMED_WAITING , TERMINATED
新建状态( NEW )
当一个 Thread 类或其子类的对象被声明并创建时,新生的线程对象处于NEW状态,称作新建状态。
即尚未启动(没有调用 start() 方法)的线程处于此状态。
可运行状态 (RUNNABLE)
处于 NEW 状态的线程,调用 Thread 类提供的 start() 方法,进入 RUNNABLE状态。
NEW 状态线程调用 start() ,让自己进入 RUNNABLE状态。
JVM 就会知道又有一个新一个线程排队等候切换了。
当 JVM 将 CPU 使用权切换给 RUNNABLE 状态的线程时,如果线程是 Thread 的子类创建的,该类中的 run() 方法就立刻执行。
如果线程是 Thread 的子类创建的,该类中的 run () 方法就立刻执行。所以我们必须在子类中重写父类的 run() 方法。
中断状态 (BLOCKED 、 WAITING 、 TIMED_WAITING)阻塞、等待、有限时间等待
死亡状态 (TERMINATED)终止
注
在主线程中用 Thread 的子类创建了两个线程,这两个线程在命令行窗口分别输出 5 句“老虎”和“小猫”;主线程在命令行窗口输出 6 句“主人”。
注意,程序在不同的计算机上运行或在同一台计算机上反复运行的结果不尽相同。
public class Tiger extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print("|老虎" + i);
try {
sleep(1000); // 状态:TIMED_WAITING
} catch (Exception exp) {
}
}
}
}
public class Cat extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
// System.out.print("|小猫"+i+"状态:"+getState()+"|");
System.out.print("|小猫" + i);
}
}
}
public class Example15_1 {
public static void main(String args[]) { // 主线程
Tiger tiger;
Cat cat;
tiger = new Tiger(); // 创建线程
cat = new Cat(); // 创建线程
System.out.println("tiger的状态:" + tiger.getState());
System.out.println("cat状态:" + cat.getState());
tiger.start(); // 启动线程
cat.start(); // 启动线程
for (int i = 1; i <= 6; i++) {
System.out.printf("\n%s", "tiger状态:" + tiger.getState());
System.out.printf("\n%s", "cat状态:" + cat.getState());
System.out.printf("\n%s", "主人" + i);
}
System.out.printf("\n%s", "|tiger的状态:" + tiger.getState());
System.out.printf("\n%s", "|cat状态:" + cat.getState());
}
}
输出(不唯一,每次线程顺序都可能不一样)
tiger的状态:NEW
cat状态:NEW
tiger状态:RUNNABLE|小猫1|老虎1|小猫2
cat状态:BLOCKED|小猫3
主人1|小猫4
tiger状态:TIMED_WAITING|小猫5
cat状态:RUNNABLE
主人2
tiger状态:TIMED_WAITING
cat状态:TERMINATED
主人3
tiger状态:TIMED_WAITING
cat状态:TERMINATED
主人4
tiger状态:TIMED_WAITING
cat状态:TERMINATED
主人5
tiger状态:TIMED_WAITING
cat状态:TERMINATED
主人6
|tiger的状态:TIMED_WAITING
|cat状态:TERMINATED|老虎2|老虎3|老虎4|老虎5
处于就绪状态的线程首先进人就绪队列排队等候 CPU 资源,同一时刻在就绪队列中的线程可能有多个。
Java 虚拟机中的线程调度器负责管理线程。
在采用时间片的系统中,每个线程都有机会获得 CPU 的使用权,以便使用 CPU 资源执行线程中的操作。
当线程使用 CPU 资源的时间到了后,即使线程没有完成自己的全部操作, Java 调度器也会中断当前线程的执行,把 CPU 的使用权切换给下一个排队等待的线程,当前线程将等待 CPU 资源的下一次轮回,然后从中断处继续执行。
Java 调度器的任务是使高优先级的线程能始终运行,一旦时间片有空闲,则使具有同等优先级的线程以轮流的方式顺序使用时间片。
在实际编程时,不提倡使用线程的优先级来保证算法的正确执行。
用 Thread 类或子类创建线程对象。
在编写 Thread 类的子类时,需要重写父类的 run() 方法,其目的是规定线程的具体操作,否则线程就什么也不做,因为父类的 run() 方法中没有任何操作语句。
例子
public class People extends Thread {
StringBuffer str;
People(String s,StringBuffer str) {
setName(s); //调用从Thread类继承的setName方法为线程起名字
this.str=str;
}
public void run() {
for(int i=1;i<=3;i++) {
str.append(getName()+","); //将当前线程的名字尾加到str 这里有可能被中断
System.out.println("我是"+getName()+",字符串为:"+str);
try { sleep(1000); // 中断状态 (TIMED_WAITING)
}
catch(InterruptedException e){}
}
}
}
public class Example15_2 {
public static void main(String args[]) {
People personOne,personTwo;
StringBuffer str=new StringBuffer();
personOne=new People("张三",str);
personTwo =new People("李四",str);
personOne.start();
personTwo.start();
}
}
输出(不唯一,每次线程顺序都可能不一样)
我是张三,字符串为:张三,李四,
我是李四,字符串为:张三,李四,
我是李四,字符串为:张三,李四,李四,张三,
我是张三,字符串为:张三,李四,李四,张三,
我是李四,字符串为:张三,李四,李四,张三,李四,张三,
我是张三,字符串为:张三,李四,李四,张三,李四,张三,
还在做笔记中,请稍等~