多线程的实现

在JAVA中,有两种方式可以实现多线程。

1、继承Thread类;

2、实现Runnable(Callable)接口。


JDK从最开始定义多线程支持时,只有两种实现要求:要么继承Thread类,要么实现Runnable接口,但是在JDK1.5开始又提供了一个新的线程接口:Callable接口。


继承Thread实现多线程:


java.long.Thread类是一个负责线程操作的类,任何类只需要继承Thread类就可以成为一个线程 的主类。但是既然是主类就必须有它的使用方法,而线程启动的主方法需要覆写Thread类中的run()方法实现,线程主体类的定义格式如下:

class 类名称 extends Thread{//继承Thread类
	属性... ;				//类中定义属性
	方法... ;				//类中定义方法
	public void run(){		//覆写Thread类中的run()方法,此方法是线程的主体
		线程主体方法 ;
	}
}

定义一个线程操作类:

class MyThread extends Thread{//这是一个多线程的操作类
	private String name ;		//定义类中的属性

	public MyThread(String name ){//定义构造方法
		this.name = name ;
	}

	@Override
	public void run(){//覆写run()方法,作为线程的主操作方法
		for(int i = 0 ; i < 200 ; i ++){
			System.out.println(this.name + "---->" + x) ;
		}
	}
}

本程序线程的主要功能是实现循环的输出操作,所有的线程与进程都是一样的,必须轮流去抢占资源,所以多线程的执行应该是多个线程彼此交替执行。也就是说,直接调用run()方法,并不能启动多线程,多线程的唯一启动方法就是Thread类中的start()方法:public void start()(调用此方法执行方法体是run()方法定义的代码)。


启动多线程:

public class Demo{
	public static void main (String [] args){
		MyThread mt1 = new Mythread("线程1") ;//实例化多线程类对象
		MyThread mt2 = new Mythread("线程2") ;
		MyThread mt3 = new Mythread("线程3") ;
		
		mt1.start() ;//启动多线程
		mt2.start() ;
		mt3.start() ;
	}
}


疑问:为什么多线程启动不是调用run()方法而是调用start()??

为了解释多线程的启动调用的问题,可以查看java.long.Thread类的start()方法的源代码:

    public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
            }
        }
    }

    private native void start0();

可以发现在start()方法里面要调用一个start0()方法,而且此方法的结构与抽象方法类似,使用了native声明。


在JAVA的开发中有一门技术被称为JNI(Java Native Interface)技术,这门技术的特点是使用Java调用本机操作系统提供的函数。但是此技术有一个缺点,就是离不开特定的操作系统。如果想要执行线程,需要操作系统来进行资源分配,所以此操作严格来主要是由JVM负责根据不同的操作系统而实现的。即使用Thread类的start()方法不仅要启动多线程的执行代码,还要根据不同的操作系统进行资源的分配。


另外,通过上述代码可以发现,在Thread类的start()方法中会抛出一个“IllegalThreadStateException”异常,本方法里面使用了throw抛出异常,本应该用try...catch...捕获异常,或者在start()方法是使用throws声明,但是此处并没有这样做,因为此异常是继承自“RuntimeException”,这样就可以由用户选择性进行性处理,如果某一个线程兑现进行了重复启动(同一个线程对象调用多次start()方法),就会抛出此异常。


实现Runnable接口:


使用Thread类的确可以方便的进行多线程的实现,但是这种方式最大的缺点就是单继承局限性,为此,在Java中也可以利用Runnable接口来实现多线程。而这个接口的定义如下:

@FunctionalInterface
interface Runnable{
	public void run() ;
}
在Runnable接口也定义了run()方法,所以只需要覆写run()方法即可。


使用Runnable接口实现多线程:

class MyThread extends implements Runnable{//这是一个多线程的操作类
	private String name ;		//定义类中的属性

	public MyThread(String name ){//定义构造方法
		this.name = name ;
	}

	@Override
	public void run(){//覆写run()方法,作为线程的主操作方法
		for(int i = 0 ; i < 200 ; i ++){
			System.out.println(this.name + "---->" + x) ;
		}
	}
}
本程序实现了Runnable接口,也正常的覆写了run()方法,但是却会存在一个问题:要启动多线程,必须调用Thread类中的start()方法,如果继承了Thread类,那么可以直接使用Thread类中的start()方法,但是Runnable接口并没有提供可以被继承的start()方法,这是该如何启动多线程呢?

通过观察Thread类可以发现,Thread类中有一个构造方法:public Thread(Runnable target),此方法可以接收一个Runnable接口对象。

利用Thread类启动多线程:

public class Demo{
	public static void main (String [] args){
		MyThread mt1 = new Mythread("线程1") ;//实例化多线程类对象
		MyThread mt2 = new Mythread("线程2") ;
		MyThread mt3 = new Mythread("线程3") ;
		
		new Thread(mt1).start() ;//启动多线程
		new Thread(mt2).start() ;
		new Thread(mt3).start() ;
	}
}
本程序首先利用Thread类的对象包装了Runnable接口对象实例,然后利用了Thread类中的start()方法启动多线程。


因为在Runnable接口的声明处使用了@FunctionalInterface的注解,证明Runnable接口是一个函数式接口,那么我们就可以使用Lambda表达式的风格编写:

public class Demo{
	public static void main (String [] args){
		String name = "线程对象" ;
		new Thread(()->{
			for(int x = 0 ; x < 200 ; x ++){
				System.out.println(name + " - - >" + x ) ;
			}		
		}).start() ;
	}
}

本程序利用Lambda表达式直接定义的线程主体实现操作,并且依然依靠Thread类的start()方法进行启动,这样的做法比直接用Runnable接口更加方便。

使用Runnable接口可以有效的避免单继承局限问题,所以在实际开发中,对于多线程的实现首选的就是Runnable接口。



面试题:请解释Thread类与Runnable接口实现多线程的区别?(请解释两种多线程实现方式的区别)

      1、Thread类是Runnable接口的子类,使用Runnable接口实现多线程可以避免单继承的局限性。

      2、Runnable接口实现的多线程可以比Thread类实现的多线程更好的描述数据共享这一概念!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值