线程的创建方式

本文介绍了Java中创建多线程的两种主要方法:继承Thread类和实现Runnable接口。通过具体示例展示了如何使用这两种方法实现多线程,并对比了它们在资源共享方面的不同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建线程有两种方式,一种是通过继承Thread类,覆盖run方法。另外一种是通过实现Runnable接口。

1 通过继承Thread类实现多线程

其步骤如下:
(1)定义类继承Thread类。
(2)覆盖Thread类中的run方法。
(3)通过Thread类的子类对象创建线程对象。
(4)调用线程对象的start方法,开启线程。
  其实线程要执行什么内容,线程自己便有定义,这个定义就是Thread中的run方法,这个方法中定义的内容就是线程要运行的内容。可是Thread中的run方法的内容并不是我们所需要的。怎么能让线程去运行我们自定义的内容呢?只有覆盖Thread类中的run方法,而覆盖之前需要先继承。这就是为什么要继承Thread类并覆盖run方法的原因。
主线程要运行的任务都在main函数中,自定义的线程要运行的任务都在run方法中。run方法就是专门用于存储线程任务代码的地方。
【例1.1】使用继承Thread类,覆盖run方法的方式创建线程。

ZiThread.java

//第一步:定义ZiThread类继承Thread类
public class ZiThread extends Thread {
    private String name;
    ZiThread(String name)
    {
        this.name = name;
    }
//第二步:覆盖Thread类中的run方法
    public void run(){
      //将线程要运行的自定义的任务都封装到了run方法中
        show();
    }
    public void show()
    {
        for(int x=1; x<=10; x++)
        {
for(int y=-99999999; y<99999999; y++){}//刻意写个循环让程序运行慢一点。
            //Thread.currentThread():获取当前执行线程的对象 
             //getName()返回该线程的名称
    System.out.println(x+":"+name+"-->"+Thread.currentThread().getName());
        }
    }
}

ThreadDemo .java

public class ThreadDemo {
    public static void main(String[] args) {
        //第三步:通过Thread类的子类对象创建线程对象
        ZiThread d1 = new ZiThread("旺财");//d1是线程对象
        ZiThread d2 = new ZiThread("小明");//d2是线程对象
        //第四步:调用线程对象的start方法,开启线程
        d1.start();
        d2.start();
/*
        线程光创建不行,还需要运行才会出现多条执行路径。 
        发现要运行线程,必须使用start方法。
        start方法做了两件事:1,开启了线程让线程可以运行,2,调用了run方法。 
        */
    }
}

运行结果:
这里写图片描述
  线程对象的d1,d2调用run方法和调用start方法有什么区别呢?调用run方法,仅仅是一般对象在调用对象中的方法,并没有开启线程,还是主线程来完成的run方法的运行。调用start方法,是开启了一个线程(一个新的执行路径)这个线程去执行了run方法。
  下面模拟售票系统来举例说明。某售票点一共有100张票,通过四个窗口卖票。卖票的动作被四个窗口同时(线程思想)使用,那就需要创建线程。可通过继承Thread类,覆盖run方法。
【例1.2】通过继承Thread类实现多进程实例。

TicketWindows.java

//第一步:定义TicketWindows类继承Thread类
public class TicketWindows extends Thread {
    private int tickets=100;
//第二步:复写父类Thread中run()方法
    public void run() {
        while(true){
            if(tickets>0){
                String name=Thread.currentThread().getName();
                System.out.println(name+"正在发售第"+tickets--+"张票");
            }
        }
    }
}

NanJingStation.java

public class NanJingStation {
    public static void main(String[] args) {
//第三步:创建四个线程对象
        NanJingStation s1=new NanJingStation();
        NanJingStation s2=new NanJingStation();
        NanJingStation s3=new NanJingStation();
        NanJingStation s4=new NanJingStation();

        s1.start();
        s2.start();
        s3.start();
        s4.start();
    }
}

运行结果:
这里写图片描述

2 通过实现Runnable接口实现多线程

步骤:
(1)定义一个类,实现Runnable接口。
(2)覆盖Runnable接口中的run方法,将线程要运行的代码存储到run方法中。
(3)创建该接口的子类对象。
(4) 通过Thread类进行线程的创建,并将Runnable接口的子类对象作为Thread类的构造函数的实参进行传递。
   为什么要传递呢?这是为了让线程对象创建时,就要明确要运行哪个run方法,而这个run方法是需要被线程对象调用的,所以将run方法所属的对象传递给Thread类的构造函数。
(5)调用Thread类中的start方法开启线程。
【例2.1】通过实现Runnable接口实现多进程实例

TicketWindows.java

//第一步:定义TicketWindows类实现Runnable类
public class TicketWindows implements Runnable {
    private int tickets=100;
//第二步:覆盖Runnable接口中的run方法
    public void run() {
        while(true){
            if(tickets>0){
                String name=Thread.currentThread().getName();
                System.out.println(name+"正在发售第"+tickets--+"张票");
            }
        }
    }
}

NanJingStation.java

public class TicketWindows {
    public static void main(String[] args) {
        //第三步:创建任务对象
        NanJingStation s=new NanJingStation();
        /*第四步:创建线程对象(将子类NanJingStation中的对象作为实参传递,便于
        知道调用的是哪个对象的run方法(这里只有一个对象t,调用的自然
        是t中的run方法))
       */
        Thread t1=new Thread(s,"窗口1");//线程处于新建状态
        Thread t2=new Thread(s,"窗口2");
        Thread t3=new Thread(s,"窗口3");
        Thread t4=new Thread(s,"窗口4");
        //第五步:开启线程
        t1.start();//线程处于就绪状态
        t2.start();
        t3.start();
        t4.start();
    }
}

运行结果:
这里写图片描述
  为什么实现了Runnable接口还需要调用Thread类中的start()方法才能启动多线程呢?这是因为Runnable接口中只有一个run()方法。也就是说,Runnable接口中并没有start()方法,所以一个类实现了RunnableJ接口也必须用Thread类中的start()方法启动多线程。

3 两种多线程实现机制的比较

  从上面的售票实例可以看出,通过继承Thread类实现多线程时,要创建4个线程对象:

        NanJingStation s1=new NanJingStation();
        NanJingStation s2=new NanJingStation();
        NanJingStation s3=new NanJingStation();
        NanJingStation s4=new NanJingStation();

        s1.start();
        s2.start();
        s3.start();
        s4.start();

  实际上是创建了4个线程对象——“南京站”,每个“南京站”有100张票。这4个线程对象各自占用各自的资源,无法达到资源共享的目的。再看通过实现Runnable接口实现多线程的方式,尽管也创建了4个线程对象(窗口),但是这里只建立了一个“南京站”,在这个“南京站”里开启了4个线程对象——窗口。它们都是操作同一个资源(“南京站”中的100张票),从而实现了资源共享的目的。

        NanJingStation s=new NanJingStation();
        Thread t1=new Thread(s,"窗口1");
        Thread t2=new Thread(s,"窗口2");
        Thread t3=new Thread(s,"窗口3");
        Thread t4=new Thread(s,"窗口4");
        //第五步:开启线程
        t1.start();
        t2.start();
        t3.start();
        t4.start();

这里写图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值