6 Java多线程机制
}
} }
public class Example6_2 { public static void main(String args[]) { Thread left = new Thread(new Lefthand()); Thread right = new Thread(new Righthand()); left.start(); right.start(); for (int i = 1; i <= 100; i++) { System.out.println("我是主线程"); } } }
时间片的CPU时间内,在若干个独立的可控制的线程之
间切换。
6.1.1 Java中的线程
Java进程中一定有主线程,负责main方法的执行。
在main方法的执行中再创建的线程,就称为程序中的
如果main方法中没有创建其他的线程,那么当main方
其它线程。
法执行完最后一个语句,JVM就会结束我们的Java应
void interrupt()
intertupt方法经常用来“吵醒”休眠的线程。当一
些线程调用sleep方法处于休眠状态时,一个占有 CPU资源的线程可以让休眠的线程调用interrupt 方
法“吵醒”自己。
6.4线程的常用方法(续)
public Thread.State getState()
6.3 使用Runnable接口
实现Runnable接口
定义run( )方法 构造线程:Thread(Runnable target);
该构造方法中的参数是一个Runnable类型的接口,因
此,在创建线程对象时必须向构造方法的参数传递一个
实现Runnable接口类的实例,该实例对象称作所创线程
的目标对象。
当线程调用start方法后,一旦轮到它来享用CPU资源,
目标对象就会自动调用接口中的run方法(接口回调)。
例子2class Lef来自hand implements Runnable { public void run() {
for (int i = 1; i <= 109; i++) {
就绪 线程创建之后就具备了运行的条件,一旦调度机
制把CPU时间片分配给线程,线程开始运行了(运行
run()方法)。
死亡 run方法结束 。 此时,调度机制将释放掉分配给 阻塞 线程能够运行,但有某个条件阻止它的运行。此
线程的内存。
时,调度机制将忽略该线程,不会给线程分配CPU时
间片。
6.1.3 启动线程
锁而陷入阻塞状态,只有等获得了同步锁,才能进入就
绪状态。
线程试图在某个对象上调用其同步控制方法,但是对 通过调用wait()使线程挂起。直到线程得到notify()或
象锁不可用。
notifyAll()消息,线程才会进入就绪状态。
线程在等待某个输入/输出完成。
6.2 Thread的子类创建线程
} else if (Thread.currentThread()==teacher) { for (int i = 1; i <= 3; i++) { System.out.println("上课!"); try { Thread.sleep(500); } catch (InterruptedException e) {} } student.interrupt(); // 吵醒student } } }
public void run() { if (Thread.currentThread()==student) { try { System.out.println(student.getName() + "正在睡觉, 不听课"); Thread.sleep(1000 * 60 * 60); } catch (InterruptedException e) { System.out.println(student.getName() + "被老师叫 醒了"); } System.out.println(student.getName() + "开始听课");
System.out.println("我是左手线程");
}
} }
class Righthand implements Runnable{ public void run() { for (int i = 1; i <= 109; i++) { System.out.println("我是右手线程");
更改线程的优先级。 int getPriority()
返回线程的优先级。
6.4线程的常用方法(续)
static Thread currentThread()
currentThread()方法是Thread类中的类方法,可以
用类名调用,该方法返回当前正在使用CPU资源的 线程。
6.4线程的常用方法(续)
返回该线程的状态。 该方法用于监视系统状态。
NEW,RUNNABLE,BLOCKED,WAITING。
例子3
本例中,有两个线程:student和teacher,其中student 准备睡一个小时后再开始上课,teacher输出3句”上课” 后,吵醒了student。 class A implements Runnable { Thread student, teacher; A() { teacher = new Thread(this); student = new Thread(this); teacher.setName("王教授"); student.setName("张三"); }
6.4线程的常用方法
void start()
线程调用该方法将启动线程,使之从新建状态进入
就绪队列排队,一旦轮到它来享用CPU资源时,就 可以脱离创建它的线程独立开始自己的生命周期了。
6.4线程的常用方法(续)
void run()
Thread类的run()方法与Runnable接口中的run()方法
public class Example6_3 { public static void main(String args[]) { A a = new A(); a.student.start(); a.teacher.start(); } }
6.5线程同步
引入同步的原因
线程同步是为了保证在多个线程访问同一个对象的
第6章
Java多线程机制
6.1 线程概述
6.2 Thread的子类创建线程
6.3 使用Runable接口
6.4 线程的常用方法
6.5 线程同步
6.6 线程之间的协作
6.7 线程联合
6.8 守护线程
6.1 线程概述
程序是一段静态的代码,它是应用软件执行的蓝本。
进程是程序的一次动态执行过程,它对应了程序从加载、
for(int i=1;i<=100;i++) { System.out.println("我是右手线程"); } }
}
public class Example6_1 { public static void main(String args[]) { Thread left=new Lefthand() ; //创建线程 Thread right=new Righthand(); left.start(); right.start(); for(int i=1;i<=100;i++) { System.out.println("我是主线程"); } } }
时候不会出现访问冲突的一种机制。
同步机制的实现
通过给对象(或类)加锁来完成线程的同步。
synchronized关键字可以作为方法的修饰符,也可
作为方法内的语句,也就是平时说的同步方法和同步
语句块。
6.5.1 同步方法
把synchronized当作实例方法修饰符时,示例代码 如下: public synchronized void methodAAA(){ //…. } 它锁定的是调用这个同步方法对象。也就是说,当 一个对象P1在不同的线程中执行这个同步方法时, 它们之间会形成互斥,达到同步的效果。但是这个 对象所属的类所产生的另一对象P2却可以任意调用 这个被加了synchronized关键字的方法。
用Thread子类创建线程对象 。
编写Thread类的子类时,需要重写父类的run方法,
其目的是规定线程的具体操作,否则线程就什么也不 做,因为父类的run方法中没有任何操作语句。
当调度机制将CPU时间片分配给线程时,如果线程是
Thread的子类创建的,该类中的run方法就立刻执行。
例子1
执行至执行完毕的一个完整过程,这个过程也是进程本 身从产生、发展至消亡的过程。
线程是比进程更小的执行单位,一个进程在其执行过程
中,可以产生多个线程,形成多条执行线索,每条线索,
即每个线程也有它自身的产生、存在和消亡的过程,也
是一个动态的概念。
Java的多线程就是在操作系统每次分时给Java程序一个
6.4线程的常用方法(续)
String getName()
返回该线程的名称。