在学习总结多线程的创建方式之前,我们先不使用多线程,只通过主线程实现的一个简单打印功能。
目的:是为了和多线程的创建使用进行对比。
代码:
package com.thread.test;
/**
* 多线程的创建
* @author jimmy
*
*/
public class First {
private String name;
public First(String name){
this.name=name;
}
public void run(){
for(int i=0;i<5;i++){
System.out.println(name+ " " +i);
}
}
public static void main(String[] args){
new First("jimmy").run();
new First("handle").run();
}
}
运行结果:
可以看出,main主线程的依次执行内容。
多线程创建的目的
创建线程的目的是为了开启一条执行路径,去运行指定代码和其他代码实现同时运行,而运行的指定代码就是这个执行路径的任务。 JVM创建的主线程的任务都定义在主函数中。 而自定义的线程它的任务: Thread类用于描述线程,线程需要任务,所以Thread类也有对任务的描述,这个任务就通过Thread类中的run方法来体现的。
也就是说,run方法就是封装自定义线程任务的函数。 run方法中定义的就是线程要运行的任务代码。
开启线程是为了运行指定代码,所以只有继承Thread类,并重写run方法。并将运行代码定义在run方法中即可。
多线程创建方式之一:继承Thread类
Java使用Thread类代表线程。所有的线程对象都是Thread类或其子类的实例。
通过继承Thread类来创建并启动多线程的步骤如下:
1·定义普通类,并继承Thread类,重写Thread类的run()方法,该run()方法体就代表了线程需要完成的任务。
2·创建Thread子类的实例,即创建了线程对象。
3·调用线程对象的start()方法来启动该线程。
代码:
package com.thread.test;
/**
* 多线程的创建
* @author 贾丽敏
*
*/
public class FirstThread extends Thread {
//private int i;
public void run(){
for(int i=0;i<5;i++){
System.out.println(getName()+" " +i );
}
}
public static void main(String[] args) throws InterruptedException{
System.out.println(Thread.currentThread().getName());
//创建第一个线程,直接实例对象即可
FirstThread f1= new FirstThread();
FirstThread f2= new FirstThread();
//创建第二个线程
f1.start();
f2.start();
}
}
执行结果:
可以看出:cpu在新创建的两个线程之间随机切换。
多线程创建方式之二:实现Runnable接口
实现Runnable接口创建线程类的步骤如下:
- 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
- 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
代码如下:
package com.thread.test;
public class SecondThread implements Runnable {
private int i;
public void run(){
for(;i<100;i++){
//当线程实现Runnable接口时,如果想获取当前线程,只能用thread.cunrentThread()方法
System.out.println(Thread.currentThread().getName()+" " +i );
}
}
public static void main(String[] args){
System.out.println(Thread.currentThread().getName());
for(int i=0;i<100;i++){
//创建Runnable对象作为线程对象的target。
//采用Runnable接口的方式创建的多想成可以共享线程类的实例变量。
SecondThread st = new SecondThread();
new Thread(st,"新线程1").start();
new Thread(st,"新线程2").start();
}
}
}
运行结果:
同样可见:cpu在两个线程之间来回切换。
两种创建多线程方式对比分析
通过Runnable接口实现达到多线程的创建方式中,Runnable对象作为Thread对象的target,Runnable实现类里包含的run()方法仅作为线程执行体。而实际的线程对象依然是Thread实例,只是改Thread线程负责执行其target的run方法。
原理很简单,代码如下:
package thread.demo;
class Thread {
private Runnable r;
Thread() {}
Thread(Runnable) {
this.r = r;
}
public void run() {
r.run();
}
public void start() {
run();
}
}
public class SubThread extends Thread {
public void run() {
System.out.println("dsa");
}
}
在Thread内部有一个私有的Runable子类对象,可以看出,当我们把Runable子类r 对象传递给Thread类构造函数的时候,启动start()就会调用run(),而run()接着调用 r 的run方法;
使用方式二创建多线程的好处:
- 避免java单继承的局限性:线程类只是实现了Runnable接口,还可以继承其它类。
- 单独封装,较好的体现了面向对象的思想。