九、多线程
9.1 并发与并行
- 并发:指两个或多个事件在同一个时间段内发生;
- 并行:指两个或多个事件在同一时刻发生(同时发生)。
注意:单核处理器的计算机肯定是不能并行的处理多个任务的,只能是多个任务在单个CPU上并发运行。同理,线程也是一样的,从宏观角度上理解线程是并行运行的,但是从微观角度上分析却是串行运行的,即一个 线程一个线程的去运行,当系统只有一个CPU时,线程会以某种顺序执行多个线程,我们把这种情况称之为线程调度。
9.2 线程与进程
- 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。
- 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程。
所有线程都可以共享进程的资源。
9.3 创建线程类
Java使用 java.lang.Thread 类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。
-
Java中通过继承Thread类来创建并启动多线程的步骤如下:
- 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把 run()方法称为线程执行体;
- 创建Thread子类的实例,即创建了线程对象 ;
- 调用线程对象的start()方法来启动该线程。
/** *教师类 **/ public class Teacher extends Thread { private String tname; private int age; @Override public void run() { while(true) { System.out.println("教师:大家好我是" + tname); } } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Teacher(String name, int age) { this.tname = name; this.age = age; } public Teacher() { } } /** *学生类 **/ public class Student extends Thread { /** * 多线程执行代码方法 */ @Override public void run() { while(true) { System.out.println("学生:大家好我是" + stuname); } } private String stuname; private int age; public String getStuname() { return stuname; } public void setStuname(String stuname) { this.stuname = stuname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student() { } public Student(String name, int age) { this.stuname = name; this.age = age; } } /** *测试类 **/ public class Test { public static void main(String[] args) { Student stu1=new Student("张三",21); Teacher t=new Teacher("赵老师",32); // stu1.run(); //启动一次线程 stu1.start(); //t.run(); //启动一次线程 t.start(); } }
-
实现Runnable接口
创建一个类实现Runnable接口,然后重写run方法
创建实现类对象、代理类对象,然后代理类对象调用start()方法启动线程/** *教师类 **/ public class Teacher implements Runnable { private String tname; private int age; @Override public void run() { while(true) { System.out.println("教师:大家好我是" + tname); } } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Teacher(String name, int age) { this.tname = name; this.age = age; } public Teacher() { } } /** *学生类 **/ public class Student implements Runnable { /** * 多线程执行代码方法(重写run方法) */ @Override public void run() { while (true) { System.out.println("学生:大家好我是" + stuname); } } private String stuname; private int age; public String getStuname() { return stuname; } public void setStuname(String stuname) { this.stuname = stuname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student() { } public Student(String name, int age) { this.stuname = name; this.age = age; } } /** *测试类 **/ public class Test { public static void main(String[] args) { Student stu1 = new Student("张三", 21); Teacher tea1 = new Teacher("赵老师", 32); Thread t1 = new Thread(stu1); Thread t2 = new Thread(tea1); t1.start(); t2.start(); } }
-
实现java.util.concurrent并发包下的Callable接口(一般不用)
创建一个类实现Callable接口,然后重写call方法并声明异常
创建一个实现类对象,执行Callable方式,需要FutureTask实现类的支持,用于接收计算结果,并创建一个线程代理类对象,启动线程。
/**
* 学生类
*/
public class Student3 implements Callable {
@Override
public Integer call() throws Exception {
for(int i=0;i<=10;i++){
System.out.println(sname + "是一名学生!");
}
return null;
}
private String sname;
private int age;
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student3(String sname, int age) {
this.sname = sname;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"sname='" + sname + '\'' +
", age=" + age +
'}';
}
}
/**
* 教师类
*/
public class Teacher3 implements Callable {
@Override
public Integer call() throws Exception {
for(int i=0;i<=10;i++){
System.out.println(tname + "是一名老师!");
}
return null;
}
private String tname;
private int age;
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Teacher3(String tname, int age) {
this.tname = tname;
this.age = age;
}
@Override
public String toString() {
return "Teacher{" +
"tname='" + tname + '\'' +
", age=" + age +
'}';
}
}
/**
* 测试类
*/
public class ThreadDemo1 {
public static void main(String[] args) {
/**
* 实现Callable接口,实现多线程
*/
Student3 stu3 = new Student3("李四",21);
Teacher3 tea3 = new Teacher3("老葛",30);
//需要FutureTask实现类的支持,用于接收计算结果
FutureTask stuFt = new FutureTask(stu3);
FutureTask teaFt = new FutureTask(tea3);
//创建线程代理类
Thread t1 = new Thread(stuFt);
Thread t2 = new Thread(teaFt);
//启动线程
t1.start();
t2.start();
}
}