Java多线程两种实现方式的对比
一种,直接继承Thread类
一种,实现Thread类的Runnable接口
两种方式的区别
比如,售票厅有四个窗口,可以发售某日某次列出的100张车票,此时,100张车票可以看作是共享资源,四个售票窗口需要创建四个线程
可以通过Thread的currentThread()方法,得到当前的线程的实例对象,然后,调用getName()方法,可以获取到线程的名称
继承Thread类,实现多线程
示例,Example04.java
public class Example04{
public static void main(String[] args){
new TicketWindow().start(); // 创建一个线程对象TicketWindows并开启
new TicketWindow().start(); // 创建一个线程对象TicketWindows并开启
new TicketWindow().start(); // 创建一个线程对象TicketWindows并开启
new TicketWindow().start(); // 创建一个线程对象TicketWindows并开启
}
}
class TicketWindow extends Thread{
private int tickets=100;
public void run(){
// 通过死循环语句,打印语句
while(true){
if (tickets>0){
// 获取当前线程
// 获取当前线程的名称
Thread th=Thread.currentThread();
String th_name=th.getName();
System.out.println(th_name+"正在发售第"+tickets--+"张票");
}
}
}
}
编译运行
可以看出,每张票都被打印了四次
原因,四个线程没有共享100张票,而是各自出售了100张票
在程序中创建了四个TicketWindow对象,就等于创建了四个售票程序,每个程序中都有100张票,每个线程在独立的处理各自的资源
注意,每个线程都有自己的名字,主线程默认的名字为main,用户创建的第一个线程的默认名字为Thread-0,第二个线程的默认名字为Thread-1,依次类推,如果,希望指定线程的名称,可以通过调用setName(String name)为线程设置名称
由于,现实生活中,系统中的车票资源是共享的,显然上面的运行结果不合理
为了保证资源共享,在程序中只能创建一个售票对象,然后,开启多个线程去运行同一个售票对象的售票方法,简单来说,就是四个线程运行同一个售票程序,此时,就需要用到线程的第二种实现方式
实现Runnable接口,实现多线程
示例,Example05.java
public class Example05{
public static void main(String[] args){
TicketWindow tw=new TicketWindow();
new Thread(tw,"窗口1").start(); // 创建线程对象,并命名为窗口1,开启线程
new Thread(tw,"窗口2").start(); // 创建线程对象,并命名为窗口2,开启线程
new Thread(tw,"窗口3").start(); // 创建线程对象,并命名为窗口3,开启线程
new Thread(tw,"窗口4").start(); // 创建线程对象,并命名为窗口4,开启线程
}
}
class TicketWindow implements Runnable{
private int tickets=100;
public void run(){
while(true){
if (tickets>0){
// 获取当前线程
// 呼气当前线程的名称
Thread th=Thread.currentThread();
String th_name=th.getName();
System.out.println(th_name+"正在发售第"+tickets--+"张票");
}
}
}
}
编译运行
代码说明
只创建了一个TicketWindow对象,然后,创建了四个线程,在每个线程上都去调用TicketWindow对象中的run()方法,这样,就可以保证四个线程访问的是同一个tickets变量,共享100张车票
可以看出,实现Runnable接口,相对于继承Thread类来说
优势如下
1、适合多个相同程序代码的线程,去处理同一个资源的情况,把线程同程序代码、数据有效的分离,很好的体现了面向对象的设计思想
2、可以避免由于Java的单继承,带来的局限性
在程序中,经常遇到这种情况,就是使用一个已经继承了某一个类的子类,创建线程,由于,一个类不能同时有两个父类,所以,不能用继承Thread类的方式,那么,只能采用实现Runnable接口的方式
实际中,大多数应用程序都会采用,实现Runnable接口的方式来创建多线程