多线程(2)线程创建的两种方法
多线程(2) 线程创建1、2
线程创建1 继承Thread类
具体步骤:
(1)创建一个继承于Thread类的子类
(2)重写Thread类的run()方法---->将此线程要执行的操作声明在此方法体中。
(3)创建当前Thread子类的对象
(4)通过对象调用start()方法;
典例如下:
public class EvenNumber {
public static void main(String[] args) {
Print p = new Print();
p.start();//调用父类中的方法。(1)启动线程(2)调用当前线程的run()方法
for (int i = 0; i <=100; i++) {
if(i%2==0)
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
class Print extends Thread{
@Override
public void run() {
for (int i = 0; i <=100; i++) {
if(i%2==0)
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
注意事项:
1) start()方法通过一系列的内部机制,包括线程状态的转换、线程调度、回调机制以及本地方法的调用,最终导致run()方法被自动执行。
而直接调用run()方法则不会启动新线程,而是在当前线程中顺序执行,因此无法实现多线程的效果。
2)不能在一个已经调用过start()方法的线程二次执行start()方法,否则报异常IllegalThreadStateException
public class OddNumber {
public static void main(String[] args) {
/* Odd o1 = new Odd();
Even e1 = new Even();
o1.start();
e1.start();*/ //标准写法
/* new Odd().start();
new Even().start();*///匿名对象
new Thread(){
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
if(i%2!=0)
System.out.println(i);
}
}
}.start();
new Thread(){
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
if(i%2==0)
System.out.println(i);
}
}
}.start();//匿名子类匿名对象
}
}
class Odd extends Thread{
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
if(i%2!=0)
System.out.println(i);
}
}
}
class Even extends Thread{
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
if(i%2==0)
System.out.println(i);
}
}
}
线程创建2 实现Runnable接口
java有单继承的限制,当我们无法继承Thread类时,那么该如何做呢?在核心类库中提供了Runnable接口,我们可以实现Runnable接口,重写run()方法,然后再通过Thread类的对象代理启动和执行我们的线程体run()方法
具体步骤:
(1)创建一个实现Runnable 接口的类
(2)实现接口中的run()方法
(3)创建实现类的对象
(4)将此对象作为参数传递到Thread类的构造器中,创建Thread类的实例
(5)Thread的实例调用start()方法
典例如下;
public class EvenNumber {
public static void main(String[] args) {
Even e1 = new Even();//创建实现类对象
Thread t1 = new Thread(e1);//创建Thread类的对象,并且把实现类的对象作为实参传给形参。调用父类中的构造器。
Thread t2 = new Thread(e1);
t1.start();//用Thread实例调用start方法
t2.start();
}
}
class Even implements Runnable{
@Override//实现Runnable类,重写run方法
public void run() {
for (int i = 0; i < 100; i++) {
if(i%2==0)
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
通过实现Runnable接口,使得该类有了多线程类的特征。所有的分线程要执行的代码都在run方法里面。
在启动多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。
说明:Runnable对象仅仅作为Thread对象的target,Runnable实现类里包含的run()方法仅作为线程执行体。 而实际的线程对象依然是Thread实例,只是该Thread线程负责执行其target的run()方法。
对比两种方式
联系
Thread类实际上也是实现了Runnable接口的类。即:
public class Thread extends Object implements Runnable
区别
- 继承Thread:线程代码存放Thread子类run方法中。
- 实现Runnable:线程代码存在接口的子类的run方法。
实现Runnable接口比继承Thread类所具有的优势
- 避免了单继承的局限性
- 多个线程可以共享同一个接口实现类的对象,非常适合多个相同线程来处理同一份资源。
- 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
结论;一般建议使用 实现Runnbale接口的方案创建多线程。