一.线程的概念模型
a.虚拟的CPU,由java.lang.Thread类封装和虚拟
b.CPU所执行的代码,传递给Thread类对象
c.CPU所处理的数据,传递给Thread类对象
二.线程体
Java的线程是通过java.lang.Thread类来实现的
每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体(即线程的可执行代码)
三.多线程
四.主线程
在任何Java程序启动时,一个线程立刻运行(即main方法对应的线程),该线程通常称为程序的主线程。
主线程的特点:
a.它是产生其他子线程的线程
b.它不一定是最后完成执行的线程,子线程可能在它结束之后还在运行。
五.创建线程
有两种方法用来创建线程:
a.声明一个Thread类的子类,并覆盖run()方法
class mythread extends Thread {
public void run() {/*覆盖访方法*/}
}
b.声明一个实现Runnable接口的类,并实现run()方法
class mythread implements Runnable {
public void run() {/*覆盖访方法*/}
}
用start()方法启动线程:
Thread t1=new Thread();
t1.start();
六.Java.lang.Thread类
常用方法:
public void start():启动该线程,将导致run方法被自动调用。该方法将立即返回,新线程将运行。
public void run():必须覆盖该方法,在方法体中添加你想要在该线程中执行的代码。
public void interrupt()://用于将一个中断请求发送给线程,不安全的,Java文档中不建议用。
public final void join(long millis) throws InterruptedException:使某个线程等待指定的时间。调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,再恢复当前线程的运行。
public static void yield():使当前正在执行的线程临时暂停,以使其它的线程运行。
实例1:
package com.bijian.thread;
//主类和线程类分开写
public class TestThread01 {
public static void main(String[] args) {
Thread t = new MyThread01();
t.start();
}
}
class MyThread01 extends Thread{
public void run() {
for(int i=0;i<5;i++) {
System.out.println("SubThread:" + i);
}
}
}
运行结果:
SubThread:0 SubThread:1 SubThread:2 SubThread:3 SubThread:4
实例2:
package com.bijian.thread;
//主类和线程类合并
public class MyThead02 extends Thread {
public static void main(String[] args) {
Thread t = Thread.currentThread();
System.out.println("主线程是:" + t);
Thread ex = new MyThead02();
ex.start();
}
public void run() {
System.out.println("子线程是:" + this);
}
}
运行结果:
主线程是:Thread[main,5,main] 子线程是:Thread[Thread-0,5,main]
七.Java.lang.Runnable接口
该接口只有一个方法:public void run();
实现该接口的类必须覆盖该方法。
实现了Runnable接口的类并不具有任何天生的线程处理能力,这与那些从Thread类继承的类是不同的。
为了从一个Runnable对象产生线程,必须再单独创建一个线程对象,并把Runnbale对象传递给它。
实例3:
package com.bijian.thread;
//主类和线程类分开写
public class TestThread03 {
public static void main(String[] args) {
MyThread03 r = new MyThread03();
Thread t = new Thread(r);
t.start();
}
}
class MyThread03 implements Runnable {
public void run() {
for(int i=0;i<3;i++) {
System.out.println("子线程No." + i);
}
}
}
运行结果:
子线程No.0 子线程No.1 子线程No.2
实例4:
package com.bijian.thread;
public class MyThread04 implements Runnable {
public static void main(String[] args) {
MyThread04 r = new MyThread04();//生成线程类(也就是本类)对象r
Thread t = new Thread(r);//创建线程对象,把线程类对象r作为参数传递给它
t.start();//启动线程t,它会自动调用线程类对象r的run方法
}
public void run() {
for(int i=0;i<3;i++) {
System.out.println("子线程No." + i);
}
}
}
运行结果:
子线程No.0 子线程No.1 子线程No.2
八.两种创建线程方法的比较
a.使用Runnable接口
可以将代码和数据分开,形成清晰的模型
还可以从其他类继承
保持程序风格的一致性
b.直接继承Thread类
不能再从其他类继承
编写简单,可以直接操纵线程,无需使用Thread.currentThread()
九.创建多线程
实例:
package com.bijian.thread;
public class TestThread05 {//主类
public static void main(String[] args) {
Runner r = new Runner();//生成线程类对象r
Thread t1 = new Thread(r);//创建线程对象t1
Thread t2 = new Thread(r);//创建线程对象t2
t1.start();//启动线程t1
t2.start();//启动线程t2
}
}
class Runner implements Runnable {//线程类
public void run() {
for(int i=0;i<3;i++) {
System.out.println("No." + i);
}
}
}
运行结果:
No.0 No.1 No.2 No.0 No.1 No.2
十.多线程共享数据和代码
对上例进行分析,可以得到下表:
线程 | 虚拟CPU | 代码 | 数据 |
t1 | Thread类对象t1 | Runner类中的run方法 | Runner类型对象r |
t2 | Thread类对象t2 | Runner类中的run方法 | Runner类型对象r |