// 重写run方法
@Override
public void run() {
// 要执行的任务
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName + ":" + i);
}
}
}
// 测试类
public class Test {
public static void main(String[] args) {
// 先创建任务对象
RunnableImpl run = new RunnableImpl();
// 然后创建Thread线程对象, 并传入线程要执行的任务
Thread t = new Thread(run);
// 调用Thread对象的start方法启动线程
t.start();
}
}
5分钟练习: 使用第二种方式创建线程
需求:
定义类: RunnableImpl, 实现Runnable接口
重写 run() 方法:
方法中for循环100次, 打印当前线程名字和次数
定义测试类, 在main()方法中:
创建RunnableImpl对象, 创建Thread对象并传入RunnableImpl对象, 启动线程
然后在 main() 方法中也for循环100次, 打印当前线程名字和次数
代码:
public class RunnableImpl implements Runnable { // Runnable代表任务
@Override
public void run() {
for (int i = 0; i < 100; i++) {
// 打印线程名字和次数
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
public class Test {
public static void main(String[] args) {
// 先创建任务对象
RunnableImpl runnable = new RunnableImpl();
// 然后直接创建Thread线程对象, 将任务传递到线程中
Thread t = new Thread(runnable);
// 使用线程对象的start方法来开启线程
t.start();
// main线程中也打印100次循环, 查看2个线程的效果
for (int i = 0; i < 100; i++) {
// 打印线程名字和次数
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
Thread和Runnable的区别
知识点:
实现Runnable接口方式 相较于 继承Thread类方式 有什么好处
总结:
实现Runnable的好处:
1. 避免单继承的局限性
2. 增强了程序的扩展性, 降低了程序的耦合性(解耦)
线程是Thread, 任务是Runnable实现类对象. 相当于将线程和任务分离
耦合性: 相互之间的关系的紧密程度
耦合性高: 相互之间的关系非常紧密
耦合性低: 相互之间的关系不太紧密
我们追求 "低耦合"
补充:
// 继承Thread类方式: 定义一个线程, 同时绑定了要执行的任务
public class MyThread extends Thread {
@Override
public void run() {
// 任务
}
}
new MyThread().start(); // 创建的线程只能执行一种任务. 任务和线程是绑定的
// 实现Runnable接口方式: 只是定义了一个任务
public class RunnableImpl implements Runnable {
@Override
public void run() {
// 任务
}
}
new Thread(new RunnableImpl()).start(); // 线程和任务相互分离, 可以创建不同的任务交给线程执行
new Thread(买菜任务).start();
new Thread(做饭任务).start();
new Thread(洗碗任务).start();
...
匿名内部类方式创建线程
知识点:
new 父接口/父类() {
重写方法
};
继承Thread类
实现Runnable接口
如何使用匿名内部类方式简化创建线程的步骤
总结:
public class Test {
public static void main(String[] args) {
// 匿名内部类方式
new Thread(new Runnable(){
@Override
public void run() {
// 要执行的任务
}
}).start();
}
}
补充:
5分钟练习: 匿名内部类创建线程
需求:
分别使用Thread子类匿名内部类方式, 和Runnable实现类匿名内部类 2种方式, 创建线程对象
线程对象内部循环100次, 打印线程名字和次数
代码:
public class Test {
public static void main(String[] args) {
// 使用匿名内部类, 简化 继承Thread类方式 创建线程
new Thread(){
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}.start();
// 使用匿名内部类, 简化 实现Runnable接口方式 创建线程
Runnable r = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
};
new Thread(r).start();
// 简化上面的代码, 直接在Thread的构造方法中, 传递匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}).start();
}
}
线程安全问题
模拟电影院卖票: 线程安全问题概述
知识点:
了解电影院卖票