十一、多线程
11.1 并发与并行
- 并发:指两个或多个事件在同一个时间段内发生;
- 并行:指两个或多个事件在同一时刻发生(同时发生)。
注意:单核处理器的计算机肯定是不能并行的处理多个任务的,只能是多个任务在单个CPU上并发运行。同理,线程也是一样的,从宏观角度上理解线程是并行运行的,但是从微观角度上分析却是串行运行的,即一个线程,一个线程的去运行,当系统只有一个CPU时,线程会以某种顺序执行多个线程,我们把这种情况称之为线程调度。
11.2 线程与进程
- 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。
- 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程。
所有线程都可以共享进程的资源。
11.3 创建线程类
Java使用 java.lang.Thread 类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。
-
Java中通过继承Thread类来创建并启动多线程的步骤如下:
- 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把 run()方法称为线程执行体;
- 创建Thread子类的实例,即创建了线程对象 ;
- 调用线程对象的start()方法来启动该线程。
/** *教师类 **/ public class Teacher1 extends Thread { @Override public void run() { while(true) { System.out.println("教师:大家好我是" + tname); } } 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 Teacher(String name, int age) { this.tname = name; this.age = age; } public Teacher() { } } /** *学生类 **/ public class Student1 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) { Student1 stu1=new Student1("张三",21); Teacher1 t=new Teacher1("老庞",32); // stu1.run(); //启动一次线程 stu1.start(); //t.run(); //启动一次线程 t.start(); /** * stu1.run() t.run() * 上述方法不可行 * 因为run方法只是一个继承父类的线程方法执行体,直接调用该方法,跟调用普通方法没有区别,是不能启动线程的 */ } }
-
实现Runnable接口(常用)
创建一个类实现Runnable接口,然后重写run方法
创建实现类对象、代理类对象,然后通过代理类对象调用start()方法启动线程/** *教师类 **/ public class Teacher2 implements Runnable { /** * 多线程执行代码方法(重写run方法) */ @Override public void run() { while(true) { System.out.println("教师:大家好我是" + tname); } } 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 Teacher(String name, int age) { this.tname = name; this.age = age; } public Teacher() { } } /** *学生类 **/ public class Student2 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) { Student2 stu1 = new Student2("张三", 21); Teacher2 tea1 = new Teacher2("老庞", 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(); } }
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/189511.html