• Thread和Runnable的区别和联系、多次start一个线程会怎么样


    一、Java有两种方式实现多线程,第一个是继承Thread类,第二个是实现Runnable接口。他们之间的联系:

        1、Thread类实现了Runable接口。

      2、都需要重写里面Run方法。

    二、实现Runnable接口相对于继承Thread类来说,有如下显著的好处:

      1、适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码,数据有效的分离,较好地体现了面向对象的设计思想。 

      2、可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。 

      3、有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程操作相同的数据,与它们的代码无关。当共享访问相同的对象是,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。

    看一下以继承Thread的卖票例子:

     
    class MyThread extends Thread{  
        private int ticket = 5;  
        public void run(){  
        	 while(true){
        		 System.out.println("Thread ticket = " + ticket--);  
                 if(ticket < 0){  
                    break;
                 }  
             }  
        }  
    }  
    public static void main(String[] args) {					
    	new MyThread().start();
    	new MyThread().start();
    			
    }
    

      输出结果:

    Thread ticket = 5
    Thread ticket = 5
    Thread ticket = 4
    Thread ticket = 4
    Thread ticket = 3
    Thread ticket = 2
    Thread ticket = 3
    Thread ticket = 1
    Thread ticket = 2
    Thread ticket = 0
    Thread ticket = 1
    Thread ticket = 0
    

     从结果可以看出:创建了两个多线程对象,他们分别实现了买票任务; 

    实现Runnable接口的卖票例子:

    class MyThread2 implements Runnable{  
        private int ticket = 5;  
        public void run(){  
        	 while(true){
        		 System.out.println("Runnable ticket = " + ticket--);  
                 if(ticket < 0){  
                    break;
                 }  
             } 
        }  
    }  
    
    
    <pre name="code" class="html">public static void main(String[] args) {
    	MyThread2 m=new MyThread2();
    	  new Thread(m).start();
    	  new Thread(m).start();
    		
    			
    }
    

    输出结果:

    1 Runnable ticket = 5
    2 Runnable ticket = 4
    3 Runnable ticket = 3
    4 Runnable ticket = 2
    5 Runnable ticket = 1
    6 Runnable ticket = 0

    从结果可以看出虽然我们声明了两个线程,但是一共卖了6张票。他们实现了资源共享。PS:在实际开发中,一定要注意命名规范,其次上面实现Runable接口的例子由于同时操作一个资源,会出现线程不安全的情况,如果情况需要,我们需要进行同步操作。

    三、线程多次调用start方法,引发的异常  

       通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。然后通过此Thread类调用方法run()来完成其运行操作的,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程终止,而CPU再运行其它线程,而如果直接用Run方法,这只是调用一个方法而已,程序中依然只有主线程--这一个线程,其程序执行路径还是只有一条,这样就没有达到写线程的目的。

      一个线程对象只能调用一次start方法.从new到等待运行是单行道,所以如果你对一个已经启动的线程对象再调用一次start方法的话,会产生:IllegalThreadStateException异常.

      可以被重复调用的是run()方法。
      Thread类中run()和start()方法的区别如下:
        run()方法:在本线程内调用该Runnable对象的run()方法,可以重复多次调用;
        start()方法:启动一个线程,调用该Runnable对象的run()方法,不能多次启动一个线程;

     

  • 相关阅读:
    为知笔记 Markdown 新手指南
    如何在服务器正确的看日志呢?
    如何查看网络之间是否互通
    自定义异常以及异常的处理
    记录下工作中用到的Linux命令
    fastJson中常用方法以及遇到的“坑”
    Java语法清单-快速回顾(开发)
    kafka的简单命令
    Elasticsearch集群状态查看命令
    ElasticSearch学习文档2018.11
  • 原文地址:https://www.cnblogs.com/wang-Java-begining/p/9901639.html
Copyright © 2020-2023  润新知