Java 创建线程对象有两种方法:
继承 Thread 类创建线程对象
实现 Runnable 接口类创建线程对象
一、继承Thread类创建线程对象
步骤:
1、定义类继承Thread.
2、复写Thread类中的run()方法
目的:将自定义代码存储在在run方法中,让线程运行
3、调用线程的start()方法。
该方法有两个作用:一是启动线程,二是调用run()方法。
当运行是会发现,每次调用运行的顺序并不相同,因为对于单核处理器来说,某一个时刻,只能有一个
在运行,多个线程在争抢CPU的执行权,CPU执行到哪个线程,哪个线程才执行。
代码实现:
package com.arain.thread;
/**
* @author arain
*
*/
class MyThread1 extends Thread{
public void run(){
//Thread.currentThread().getName()等同于this.getName()
System.out.println(Thread.currentThread().getName() + " is running!");
}
}
public class MyThread {
/**
* @param args
*/
public static void main(String[] args) {
MyThread1 myThread = new MyThread1();
Thread t1 = new Thread(myThread, "t1");
Thread t2 = new Thread(myThread, "t2");
Thread t3 = new Thread(myThread, "t3");
Thread t4 = new Thread(myThread, "t4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
说明:
程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建。随着调用MyThread的两个对象的start方法,另外两个线程也启动了,这样,整个应用就在多线程下运行。
start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。
从程序运行的结果可以发现,多线程程序是乱序执行。因此,只有乱序执行的代码才有必要设计为多线程。
为什么要复写run()方法呢?因为Thread用户描述线程,它定义了run()方法用于存储线程需要执行的代码,但是并没有实现,需要根据需要进行复写。
二、实现Runnable类
步骤:
1,实现Runnable接口。
2,覆盖run方法。
3,通过Thread类创建线程对象。
4,将Runnable接口的子类对象作为实参传递给Thread类中的构造函数。
因为自定义的run()方法所属的对象是Runnable接口的子类对象,要让线程去执行指定的run方法,就必
须明确run()方法所属具体对象。
5,调用start方法开启线程,并运行Runnable接口子类的run方法。
实现Runnable接口创建线程思想:
将线程任务和线程对象进行解耦,将线程任务单独封装成对象。
实现Runnable接口可以避免单继承的局限性。
所以建议创建多线程,都是用实现Runnable接口的方式。
实现:
class Ticket implements Runnable
{
private int num = 100;
public void run()
{
while(true)
{
if(num>0)
{
System.out.println(Thread.currentThread().getName()+"..sale:"+num--);
}
}
}
}
class ThreadDemo3_Ticket_Runnable
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
实现方式和继承方式的区别:
实现方式的优点:避免了单继承的局限性,在定义线程时,建议使用该方式。
区别:
继承Thread:线程代码存放在Thread子类run方法中
实现Runnable:线程代码存在接口的子类run()方法。