多线程的原理
举例说明
// 创建一个Thread类的子类
public class MyThread extends Thread{
// 在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程后要做什么)
@Override
public void run(){
for (int i = 0; i< 20;i++){
System.out.println("run:" + i);
}
}
public static void main(String[] args) {
// 创建一个Thread类的子类
MyThread mt = new MyThread();
mt.start();
// 主线程会继续执行的主方法中的代码
for (int i = 0; i< 20; i++) {
System.out.println("main:" + i);
}
}
// 最终得到的结果使随机的,run方法中和main方法中遍历的数随机分布的
程序执行得到的结果是随机的,如下图所示:
原理图:
多线程的好处是各个线程之间互不影响,某一个出了问题不会影响别的线程,每当新创建一个线程就会在内存中新开辟一个栈空间用于新的线程执行
Thread类
1、Thread中的常用方法
构造方法
public Thread()
:分配一个新的线程对象public Thread(String name)
:分配一个指定名字的新的线程对象public Thread(Runnable target)
:分配一个带有指定目标新的线程对象public Thread(Runnable target,String name)
:分配一个带有指定目标新的线程对象并指定名字
常用方法:
public String getName()
:获取当前线程的名称public void start()
:导致此线程开始执行;Java虚拟机调用此线程的run方法public void run()
:此线程要执行的任务在此处定义代码public static void sleep(long millis)
:使当前正在执行的线程已制定的毫秒数暂停(暂时停止运行)public static Thread currentThread()
:返回当前正在执行的线程对象的引用
创建线程方式二(实现Runnable接口)
Thread类中有两个构造方法可以传入Runnable类的对象分别是
public Thread(Runnable target)
和public Thread(Runnable target,String name)
,我们可以利用这两个构造方法使用Runnable接口创建新的线程
1、实现步骤
① 创建一个Runnable接口的实现类
② 在实现类中重写Runnable接口的实现类对象
③ 创建一个Runnable接口的实现类对象
④ 使用构造方法中传递Runnable接口的实现类对象创建Thread类对象
⑤ 调用Thread类中的start方法,开启新的线程执行run方法
2、举例说明
// 创建一个Runnable的实现类
public class RunnableImpl implements Runnable {
// 在实现类中重写Runnable接口中的run方法,用来设置线程任务
public void run(){
for (int i = 0; i < 20; i++){
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
}
public static void main(String[] args) {
// 创建一个Runnable接口实现类的对象
RunnableImpl run = new RunnableImpl;
// 创建Thread类对象,构造方法中传递Runnable接口的实现类对象
Thread t = new Thread(run);
// 调用Thread类中的start方法,开启线程执行run方法
t.start();
for (int i = 0; i < 20; i++){
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
结果如图所示:
使用Runnable接口实现类创建新的线程的好处
- 避免了单继承的局限性
一个类只能继承一个类,类继承了Thread类就不能继承其他的类了,如果使用Runnable接口创建新的线程的话,还可以继承其他的类,也能实现其他的接口 - 增强了程序的扩展性,降低了程序的耦合性(解耦)
实现了Runnable接口的方式,把设置线程任务和开启线程任务进行了分离,这就叫做解耦
实现类中,重写了run方法:用来设置线程任务
创建Thread类对象,调用了start方法:用来开启新的线程
匿名内部类方式实现线程的创建
1、匿名内部类的作用是什么?
简化代码;把子类继承父类,子类重写父类的方法,创建子类的对象合成一步完成;把实现接口,实现类重写接口中的方法,创建实现类对象合成一步完成
2、格式:
new 父类/接口(){
重写父类/接口中的方法
};
3、举例说明
public static void main(String[] args) {
// 使用Thread类创建新的线程
// 正常情况我们需要先创建Thread类的子类,然后覆盖重写run方法,然后创建子类的对象,最后使用创建的对象调用start方法开启线程任务
new Thread(){
// 重写run方法,设置线程任务
@Override
public void run() {
for (int i = 0 ; i <20 ; i++ ) {
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
}.start();
// 使用Runnable接口创建新的进程
Runnable r = new Runnable() {// 一个多态的写法,Runnable的实现类对象向上转型为Runnable类型
// 重写run方法,设置线程任务
@Override
public void run() {
for (int i = 0 ; i <20 ; i++ ) {
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
};
new Thread(r).start();
// 使用Runnable接口创建新的进程的另一种写法
new Thread(new Runnable() {// 一个多态的写法,Runnable的实现类对象向上转型为Runnable类型
// 重写run方法,设置线程任务
@Override
public void run() {
for (int i = 0 ; i <20 ; i++ ) {
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
}).start();
}