一、能够避免因为Java的单继承特性而带来的局限;sql
二、加强程序的健壮性,代码可以被多个线程共享,代码与数据是独立的;安全
三、适合多个相同程序代码的线程区处理同一资源的状况。多线程
下面以典型的买票程序(基本都是以这个为例子)为例,来讲明两者的区别。架构
首先经过继承Thread类实现,代码以下:并发
class MyThread extends Thread{ private int ticket = 5; public void run(){ for (int i=0;i<10;i++) { if(ticket > 0){ System.out.println("ticket = " + ticket--); } } } } public class ThreadDemo{ public static void main(String[] args){ new MyThread().start(); new MyThread().start(); new MyThread().start(); } }
某次的执行结果以下:分布式
从结果中能够看出,每一个线程单独卖了5张票,即独立地完成了买票的任务,但实际应用中,好比火车站售票,须要多个线程去共同完成任务,在本例中,即多个线程共同买5张票。高并发
下面是经过实现Runnable接口实现的多线程程序,代码以下:性能
class MyThread implements Runnable{ private int ticket = 5; public void run(){ for (int i=0;i<10;i++) { if(ticket > 0){ System.out.println("ticket = " + ticket--); } } } } public class RunnableDemo{ public static void main(String[] args){ MyThread my = new MyThread(); new Thread(my).start(); new Thread(my).start(); new Thread(my).start(); } }
某次的执行结果以下:学习
从结果中能够看出,三个线程一共卖了5张票,即它们共同完成了买票的任务,实现了资源的共享。spa
针对以上代码补充三点:
一、在第二种方法(Runnable)中,ticket输出的顺序并非54321,这是由于线程执行的时机难以预测,ticket–并非原子操做。
二、在第一种方法中,咱们new了3个Thread对象,即三个线程分别执行三个对象中的代码,所以即是三个线程去独立地完成卖票的任务;而在第二种方法中,咱们一样也new了3个Thread对象,但只有一个Runnable对象,3个Thread对象共享这个Runnable对象中的代码,所以,便会出现3个线程共同完成卖票任务的结果。若是咱们new出3个Runnable对象,做为参数分别传入3个Thread对象中,那么3个线程便会独立执行各自Runnable对象中的代码,即3个线程各自卖5张票。
三、在第二种方法中,因为3个Thread对象共同执行一个Runnable对象中的代码,所以可能会形成线程的不安全,好比可能ticket会输出-1(若是咱们System.out….语句前加上线程休眠操做,该状况将颇有可能出现),这种状况的出现是因为,一个线程在判断ticket为1>0后,尚未来得及减1,另外一个线程已经将ticket减1,变为了0,那么接下来以前的线程再将ticket减1,便获得了-1。这就须要加入同步操做(即互斥锁),确保同一时刻只有一个线程在执行每次for循环中的操做。而在第一种方法中,并不须要加入同步操做,由于每一个线程执行本身Thread对象中的代码,不存在多个线程共同执行同一个方法的状况。
欢迎工做一到五年的Java工程师朋友们加入Java架构开发 : 867748702 群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、 Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper, Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料) 合理利用本身每一分每一秒的时间来学习提高本身, 不要再用"没有时间“来掩饰本身思想上的懒惰!趁年轻,使劲拼,给将来的本身一个交代!