Thread和Runnable实现多线程的区别终极剖析!

   在java中可以通过继承Thread,并重写里面的run()方法实现线程,如下:
public class MyThread  extends Thread{
        private String number;
        
        public MyThread(String number){
        	this.number=number;
        }

		@Override
		public void run() {
			for(int i=0;i<30;i++){
			System.out.println("Thread"+number+" 已经运行,number i="+i);
		}
        
        
		}
        
}

调用过程:

public class ThreadDemo {
        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();//启动线程三号
        }
}
通过start()方法启动线程,会通过JVM调用run()方法,但是为什么不直接调用run()方法呢?我们看一下java的源代码中是怎么写的
    public synchronized void start() {
        /**
	 * This method is not invoked for the main method thread or "system"
	 * group threads created/set up by the VM. Any new functionality added 
	 * to this method in the future may have to also be added to the VM.
	 *
	 * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
	    stop0(throwableFromStop);
	}
    }

    private native void start0();
线程的启动会根据占用cpu的多少来启动线程,而上面的native所声明的start0()的作用就是调用操作系统的底层,进而可以对进程达到控制的目的.


下面介绍第二种方式implements runnable()

       这种方法是通过实现runnable接口,所以你可以知道相比extends Thread,你可以多次实现各种接口,但是继承就不行了,你要是继承Thread,你就休想再继承别的东西了,所以这是使用runnable()的第一个好处,下面是使用Runnable的实现:

public class MyThread  implements Runnable{
        private String number;
        
        public MyThread(String number){
        	this.number=number;
        }


		@Override
		public void run() {
			for(int i=0;i<30;i++){
			System.out.println("Thread"+number+" 已经运行,number i="+i);
		}
        
        
		}
        
但是调用方式和Thread有所不同,实现Runnable这个接口要使用Thread的构造方法,截图一会传上来.然后启动
public class ThreadDemo {
        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();//启动线程三号
        }
}




这两种方法的第二个区别就是使用Runnable()这个接口,可以实现资源共享:下面看例子:

package com.线程卖票1;

 class MyThread extends Thread {
	private int ticket=6;

	@Override
		public void run() {
			for(int i=0;i<30;i++){
				if(ticket>0){
			System.out.println("卖票="+this.ticket--);
		}
        
			}
		}
}

public class ThreadDemo {
        public static void main(String args[]){
        	MyThread mt1=new MyThread();//一个线程
        	MyThread mt2=new MyThread();//两个线程
        	MyThread mt3=new MyThread();//三个线程
        	  
        	mt1.start();//启动线程一号
        	mt2.start();//启动线程二号
        	mt3.start();//启动线程三号
        }
}
结果:
卖票=6
卖票=5
卖票=4
卖票=3
卖票=2
卖票=1
卖票=6
卖票=6
卖票=5
卖票=5
卖票=4
卖票=4
卖票=3
卖票=3
卖票=2
卖票=2
卖票=1
卖票=1

上面取了十多张票,但是只有六张,除非你家是铁路局的,否则你多出来的票是哪来的?

下面看implements Runnable()实现的:

package com.线程卖票2;
 class MyThread implements Runnable {// 实现Runnable接口
	private int ticket = 5; // 一共才5张票


	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			if (this.ticket > 0) {
				System.out.println("卖票:ticket = " + this.ticket--);
			}
		}
	}
}


public class ThreadDemo {
	public static void main(String[] args) {
		MyThread mt = new MyThread(); // 一个线程
		new Thread(mt).start() ;	// 开始卖票
		new Thread(mt).start() ;	// 开始卖票
		new Thread(mt).start() ;	// 开始卖票
	}


}

结果:
卖票:ticket = 5
卖票:ticket = 2
卖票:ticket = 1
卖票:ticket = 4
卖票:ticket = 3
第二种实现方式的有点显而易见,就是可以实现资源共享!!!!!!!!!!!!!!!!!!!!
下面对程序进行剖析:  





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值