浅谈Java多线程之Threa类和Runnable接口的区别

众所周知Java多线程通过两种方式创建:一种是继承Thread类,另一种是实现Runnable接口。那么,两种方式有什么区别?哪种方式更好些?  

Thread类定义在Java.lang包中,只要继承Thread类同时覆写本类的run()方法就能操作多线程,但一个类只能继承一个父类,这是继承Thread类的局限。

Thread类示例:

class Test extends Thread{  
	private String name;  
	public Test(String name){  
		super();
		this.name = name;
	}  
	public void run(){  
		for(int i=0;i<10;i++){  
			System.out.println("线程启动:"+this.name+",i="+i);  
		}  
	}  
}   
public class ThreadTest{  
	public static void main(String[] args){  
		Test t1=new Test("线程A");  
		Test t2=new Test("线程B");  
		t1.run();  
		t2.run();  
	}  
}

结果很有规律,第一个对象先执行,然第二个对象再执行,并没有相互交替运行,说明线程没启用,只是普通的方法调用。查看JDK文档发现一旦调用start()方法,则通过JVM找到run()方法启动线程。

public class ThreadTest{  
	public static void main(String[] args){  
		Test t1=new Test("线程A");  
		Test t2=new Test("线程B");  
		t1.start();  
		t2.start();  
	}  
}

这样程序能正常完成交互式运行,为什么非要使用start()方法启动多线程?

在JDK安装目录下,src.zip是Java源程序,通过此找到Thread类的start()方法的定义,发现使用private native void start();其中native关键字表示允许调用操作系统的底层函数,这样的技术称为JNI技术(Java Native Interface)。

Runnabl接口示例:

实际开发中多线程操作较少使用Thread类,主要通过Runnable接口完成。

class Test implements Runnable{  
	private String name;  
	public Test(String name){  
		this.name = name;
	}  
	public void run(){  
		for(int i=0;i<10;i++){  
			System.out.println("线程启动:"+this.name+",i="+i);  
		}  
	}  
}   
public class RunnableTest{  
	public static void main(String[] args){  
		Test t1 = new Test("线程1");
		Test t2 = new Test("线程2");
		new Thread(t1).start();
		new Thread(t2).start();		
	}  
}

使用Runnable接口定义的子类没有start()方法,只有Thread类中才有。通过JDK文档查看Thread类有一构造方法:Public Thread(Runnable targer)接受Runnable的子类实例,也就是说通过Thread类启动start()方法实现Runnable的多线程。

两种实现方式的区别和联系:

程序开发中多线程永远以实现Runnable接口为主,因为和继承Thread类相比有如下好处:

1、避免单继承的局限,Java中一个类允许实现多个接口;

2、适合于资源的共享。

Thread类卖票程序:

class Ticket extends Thread{
	private int tick=10;
	public void run(){
		while(true){
			if(tick>0)
				System.out.println(Thread.currentThread().getName()+"...SaleTikcet...."+tick--);
		}
	}
}
class TicketDemo{
	public static void main(String[] args)	{
		Ticket t1 = new Ticket();
		Ticket t2 = new Ticket();
		Ticket t3 = new Ticket();
		t1.start();//每个线程都各卖10张,共计30张票,
		t2.start();//实际只有10张票,每个线程都各卖各的,
		t3.start();//没有达到资源共享目的。
	}
}
如果用Runnable接口就能实现资源共享,示例如下:

class Ticket implements Runnable{
	private int tick = 10;
	public void run(){
		while(true){
			if(tick>0)
			{			
				System.out.println(Thread.currentThread().getName()+"...SaleTicket..."+tick--);
			}
		}
	}
}
class TicketDemo2{
	public static void main(String[] args){
		Ticket t = new Ticket();		
		new Thread(t).start();//同一t,在Thread类中不可以,
		new Thread(t).start();//如果同一个实例化对象,会报异常。
		new Thread(t).start();	
	}
}
现在程序中有三个线程,但一共只卖了10张票,达到了资源共享目的。

通过查看JDK文档发现:public class Thread extends Object implements Runnable ,说明Thread类也是Runnable接口的子类。 


PS:初碰Java,网上搜索到许多这样的文章;口语化严重,措辞生硬晦涩, 忍不住想整改。借用模板重新编写,原作者不详,看到请告之。

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt多线程是Qt框架提供的一种多线程编程的解决方案,通过创建和管理多个线程,可以实现在程序中同时执行多个任务的能力。Qt提供了QThread和QtConcurrent命名空间来支持多线程。 QThread是Qt提供的多线程编程的基础,它封装了与底层操作系统调用相关的函数,并提供了一套简单的API来管理线程的生命周期。通过继承QThread,我们可以创建自己的线程,并实现线程执行体run()函数。调用线程的start()函数即可启动线程,并在run()函数中实现需要在新线程中执行的任务。另外,QThread还提供了其他一些方法,如wait()、msleep()等,用于线程的控制。 QtConcurrent命名空间是Qt提供的一个高级多线程编程的工具,其使用起来更加简单方便。QtConcurrent可以运行同步和异步的任务,主要通过函数调用和lambda表达式来实现。我们可以使用QtConcurrent提供的函数,比如map()、filter()等,将任务分解成多个小的任务,并在多个线程中同时执行。使用QtConcurrent,我们只需要关注任务的输入和输出,而无需关注线程的创建和管理。 无论是使用QThread还是QtConcurrent命名空间,Qt多线程都遵循的原则是将任务分解成小的子任务,并在多个线程中同时执行,以提高程序的性能和响应速度。同时,Qt多线程也提供了线程间的通信机制,例如使用信号与槽机制、使用QMutex、QSemaphore等同步对象来保证数据的正确访问。 需要注意的是,在多线程编程中,我们需要注意线程之间的同步和互斥,以避免资源竞争和数据不一致等问题。Qt提供了多种同步和互斥的机制,如互斥锁、条件变量等,可以根据具体的需求选择合适的方式来保证线程之间的安全性。 总之,Qt多线程提供了一种方便易用的多线程编程解决方案,使我们可以在Qt程序中充分利用多核处理器的能力,提高程序的性能和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值