线程创建方式2: 实现Runnable接口
大纲:
1. 线程的创建方式一:继承Thread类
1.1 步骤:
(1)创建一个继承于Thread类的子类
(2)重写Thread类的run()方法--->将此线程要执行的操作,声明在方法体中
(3)创建当前Thread的子类的对象
(4)通过对象调用start()方法
start()方法作用:1.启动线程 2.调用当前线程的run()方法
1.2 例题:创建一个分线程1,用于遍历100以内的偶数
【拓展】 再创建一个分线程2,用于遍历100以内的偶数
2.线程的创建方式二:实现Runnable接口
2.1 步骤:
(1)创建一个实现Runnable接口的类
(2)实现接口中的Run() ---> 将此线程要执行的操作,声明在方法体中
(3)创建当前实现类的对象
(4)将此对象作为参数传递到Thread类的构造器中,创建Thread类的实例
(5)Thread类的实例调用start()方法
start()方法作用:1.启动线程 2.调用当前线程的run()方法
2.2 例题:创建分线程遍历100以内的偶数
3.对比两种方式?
共同点:(1)启动线程,使用的都是Thread类中定义的start()
(2)创建的线程对象,都是Thread类或其子类的实例。
不同点:一个是类的继承,一个是接口的实现。
建议:建议使用实现Runnable接口的方式。
Runnable方式的好处:(1)实现的方式,避免了类的单继承的局限性
(2)更适合处理有共享数据的问题
(3)实现了代码和数据的分离。
联系:public class Thread implements Runnable(代理模式)
代码举例:
package thread.demo01.runnable;
/*
线程的创建方式二:实现Runnable接口
步骤:
(1)创建一个实现Runnable接口的类
(2)实现接口中的Run() ---> 将此线程要执行的操作,声明在方法体中
(3)创建当前实现类的对象
(4)将此对象作为参数传递到Thread类的构造器中,创建Thread类的实例
(5)Thread类的实例调用start():1.启动线程 2.调用当前线程的run()
*/
public class EvenNumberTest {
public static void main(String[] args) {
//(3)创建当前实现类的对象
EvenNumberPrint r1 = new EvenNumberPrint();
//(4)将此对象作为参数传递到Thread类的构造器中,创建Thread类的实例
Thread t1 = new Thread(r1);
//(5)Thread类的实例调用start():1.启动线程 2.调用当前线程的run()
t1.start();
//main()方法对应的主线程执行的操作
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
/*
拓展:再创建一个线程,遍历100以内的偶数
*/
Thread t2 = new Thread(r1);
t2.start();
}
}
//(1)创建一个实现Runnable接口的类
class EvenNumberPrint implements Runnable{
//(2)实现接口中的Run() ---> 将此线程要执行的操作,声明在方法体中
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
练习:创建两个分线程,其中一个线程遍历100以内的偶数,另一个线程遍历100以内的奇数。
这里主要看方式3
package thread.demo01.exercise1;
public class PrintNumberTest {
public static void main(String[] args) { //main()主线程
//方式1:
// Even t1 = new Even();
// Odd t2 = new Odd();
// t1.start();
// t2.start();
//方式2:创建Thread类的匿名子类的匿名对象。
new Thread(){ //偶数
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ": ---- " + i);
}
}
}
}.start();
new Thread(){ //奇数
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 != 0){
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
}.start();
//方式3:使用实现Runnable接口的方式:提供了Runnable接口匿名实现类的匿名对象
new Thread(new Runnable() {
@Override
public void run() { //100以内偶数
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ": ---- " + i);
}
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
for(int i = 1; i <= 100; i++){
if (i % 2 != 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}).start();
}
}
class Even extends Thread{ //用于打印偶数
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ": ---- " + i);
}
}
}
}
class Odd extends Thread{ //用于打印奇数
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 != 0){
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
}
思考1:判断各自调用的是哪个run()?
package thread.demo01.exercise2;
/*
思考题:判断各自调用的是哪个run()?
*/
public class Exercise {
public static void main(String[] args) {
A a = new A();
a.start();//(1)启动线程 (2)调用Thread类的run() 输出:线程A的run()...
B b = new B(a);
b.start();//输出:线程B的run()...
//start():导致此线程开始执行; Java虚拟机调用此线程的run方法。
}
}
//创建线程类A
class A extends Thread{
@Override
public void run() {
System.out.println("线程A的run()...");
}
}
//创建线程类B
class B extends Thread{
private A a;
public B(A a) { //构造器中,之间传入A类对象
this.a = a;
}
@Override
public void run() {
System.out.println("线程B的run()...");
}
}
思考2:
package thread.demo01.exercise2;
public class Exercise_1 {
public static void main(String[] args) {
BB b = new BB();
new Thread(b){
@Override
public void run() {
System.out.println("CC的run()...");
}
}.start();//CC的run()...
//new Thread(){}.start(); //什么都没有
}
}
class AA extends Thread{
@Override
public void run() {
System.out.println("AA的run()...");
}
}
class BB implements Runnable{
@Override
public void run() {
System.out.println("BB的run()...");
}
}