初识线程1(java版)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

前言

提示:以下是本篇文章正文内容,下面案例可供参考

一、线程与进程的关系?

1.最小资源分配单元与最小执行单元

  进程顾名思义就是指正在执行的程序,同时进程也是操作系统进行资源分配的最小单位,进程可进一步细化为一个或多个线程,故线程隶属于进程,早期的程序都是单线程的,后来因为不断省级的业务需求,同时为了提高程序的执行效率,同一个进程中往往有多个线程在执行任务,所以从这个角度来说,线程是进程中的最小执行单元,作为执行的最小执行单元,线程也就成了操作系统进行任务调度的最小单元

2.互相依赖

  一个进程,即一个运行的应用程序中有无数个线程为该进程执行任务,故无数个线程共同执行并完成了它们所属的进程的任务,而进程作为操作系统资源分配的最小单位,为所有内部线程提供来自操作系统分配的资源,二者之间的关系可以简单地总结为:

一个线程只能属于一个进程,一个进程中至少有一个线程(主线程),进程启动时,需要向操作系统注册,并由操作系统为该进程分配运行时内存,并将该进程装入内存空间.

这也就很好地解释了线程为什么不能脱离进程而存在,线程依赖于进程所在的运行时存在,而该内存是由操作系统分配的临时内存,这意味着一旦该进程终止运行,该内存便会由操作系统进行回收

二、JAVA中创建线程两种常用方式

1.继承Thread类

代码如下(示例):

public class MyThread extends Thread{
    
    //继承Thread类并实现run()方法
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName()+":"+(i+1));
        }
    }
}

这是Java中实现线程的最简单的方式,可以看到实质是对Thread类做了一个简单的扩展

该方法要求用户自定义一个继承了Thread的类,同时需要实现Thread类中的run()

Thread类是java中提供的对线程进程管理的类,可以看到run()中主要写了该线程需要执行的任务,

即希望线程完成什么样的任务

为什么一定要实现run()

public class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }

通过上面这一段代码我们可知Thread类继承了Runnable接口,而在Runnale接口中

public interface Runnable {
    /**
     * When an object implementing interface {@code Runnable} is used
     * to create a thread, starting the thread causes the object's
     * {@code run} method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method {@code run} is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

可以看到Runnable接口中只有一个抽象方法run()

该方法定义了线程需要执行的任务

在实现了run()方法之后,只需要在主方法也就是主线程中创建线程对象并调用线程对象的start()即可

例如:

public static void main(String[] args) {
        //实现多线程的第一种方式,自定义类继承Thread类,并重写run()
        //创建线程类对象并启动MyThread线程
        MyThread mt=new MyThread();
        //调用start()启动当前线程
        mt.start();
    }

需要注意的是start()的作用是启动当前线程对象去执行run()中定义的线程任务,start()的实质是由操作系统对当前线程进行任务调度(这一过程是需要向操作系统注册的)

2.实现Runnable接口

代码如下(示例):

class Mythread1 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"优先级为");
            System.out.println(Thread.currentThread().getPriority());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

对比第一种直接继承的方式,二者均实现了Runnable接口中的run();其原因是Thread线程管理类也实现了Runnale这个顶级接口,而Runnable只唯一定义了run()方法

同样两种方式中run()的作用是相同的,即定义线程任务功能.

采用实现Runnable接口方式,我们需要在主线程中创建线程管理类Thread,同时将实现了

Runnable接口的自定义类的实例当做线程任务类对象传入,以下代码作为参考

public static void main(String[] args) {
        //创建两个线程任务类,实现交替打印输出当前线程的优先级
        Thread thread=new Thread(new Mythread1());
               thread.setName("线程1");
               thread.setPriority(1);
        Thread thread1=new Thread(new Mythread1());
               thread1.setName("线程2");
               thread1.setPriority(10);
        //启动两个线程交替打印
        thread.start();
        thread1.start();
    }
public Thread(Runnable target) {
    this(null, target, "Thread-" + nextThreadNum(), 0);
}

通过分析第二段源码我们可以知道Mythread1对象被当做target参数传入Thread的有参构造方法中

但在实际应用中我们多用第二种方式,原因在于第一种方式是直接继承并实现了Thread类中的run(),众所周知类与类之间的继承是单继承的,故第二种实现方式很好地避免了单继承的局限性,除此之外,采用第二种实现方式可以使得多个线程共享同一个Runnable接口实现类对象,即多个线程可以对同一个对象进行处理,这点是第一种方式无法媲美的。


总结

以上就是今天要讲的内容,本文仅仅简单介绍了线程与进程的关系以及Java中两种常用的实现线程的方式。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值