1、线程介绍
进程(process)是指在系统中正在运行的一个应用程序,是系统资源分配的基本单位,在内存中有其完备的数据空间和代码空间,拥有完整的虚拟空间地址。一个进程所拥有的数据和变量只属于它自己。
线程(thread)是进程内相对独立的可执行单元,所以也被称为轻量进程(lightweight processes);是操作系统进行任务调度的基本单元。它与父进程的其它线程共享该进程所拥有的全部代码空间和全局变量,但拥有独立的堆栈(即局部变量对于线程来说是私有的)。
当一个程序开始运行时,它就是一个进程,进程包含运行中的程序和程序所使用的内存和系统资源。而一个进程又是由多个线程组成的。引入线程优点是易于调度,提供开发效率,通过线程可以方便有效的实现并发,进程可创建多个线程来执行同一个程序的不同部分,开销小,创建线程比创建进程要快,所需开销很少。
2、Runable和Thread的关系
在java中可有两种方法实现多线程,一种是继承Thread类,一种是实现Runnable接口;
2.1 继承Thread类
class TestThread extends Thread{ private String name; public TestThread(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 ThreadDemo { public static void main(String[] args) { TestThread tt1 = new TestThread("这里是张三"); TestThread tt2 = new TestThread("这里是李四"); tt.start(); tt.start(); } }
2.2 实现Runnable接口
代码如下:
public class TestThread implements Runnable{ private String name; public TestThread(String name) { super(); this.name = name; } public void run() { for(int i = 0;i < 10;i++) { System.out.println("线程信息:" + this.name + ",i = " +i); } } }
然而在Runnable的子类中没有start() 方法,只有Thread类中才有 。此时视察Thread类,有一个构造函数:public Thread(Runnable targer) 此构造函数接受Runnable的子类实例,也就是说可以通过Thread类来启动Runnable实现多线程 。(start() 可以协调系统的资源):
public class ThreadDemo { public static void main(String[] args) { TestThread tt1 = new TestThread("这里是张三"); TestThread tt2 = new TestThread("这里是李四"); new Thread(tt1).start(); new Thread(tt2).start(); } }
3、实际中如何应用这两种实现模式
在程序实现多线程应优先以实现Runnable接口为主,由于实现Runnable接口相比继承Thread类有如下好处:
(1)避免点继承的局限,一个类可以继承多个接口 。
(2)利于资源的共享。
以卖票程序为例,通过Thread类实现:
class TicketThread extends Thread { private int ticket = 1000; public void run(){ for(int i = 0;i < 1000;i++) { if(this.ticket > 0){ System.out.println("卖票:ticket"+this.ticket--); } } } }
下面通过三个线程对象,同时卖票:
public class ThreadTicket { /** * 继承Thread */ public static void startThread(){ TicketThread tt1 = new TicketThread(); TicketThread tt2 = new TicketThread(); TicketThread tt3 = new TicketThread(); tt1.start();//每个线程都各卖了1000张,共卖了3000张票 tt2.start(); tt3.start(); } /** * 实现Runable接口 */ public static void startRunable(){ TicketThread tt = new TicketThread(); new Thread(tt).start();//同一个mt new Thread(tt).start(); new Thread(tt).start(); } public static void main(String[] args) { startThread(); startRunable(); } }
现在程序中有三个线程,然而一共卖了10张票,也就是说使用Runnable实现多线程可以达到资源共享的目的。
4、Runnable接口和Thread的关系总结
(1) 说白了就是类和接口的区别。Thread是一个类,java中是不允许继承多个父类的,这就是Thread的一个局限性。而使用Runnable就不同了,可以implements多个接口,同时继承一个父类,这样会更加灵活。
(2) 当多个线程需要共享资源时,用Thread很难达到目的,但是用Runnable接口就容易许多了。
(3) 二者的联系:看源码可以发现,Thread其实就是继承了Runnable接口的子类。