多线程的相关知识

本文介绍了程序、进程和线程的概念,并详细阐述了Java中多线程的创建方式,包括继承Thread类、实现Runnable接口以及实现Callable接口。通过实例展示了三种创建线程的方法,并对比了它们的优缺点。多线程能够提高应用程序响应速度和CPU利用率,适用于需要同时执行多个任务或进行等待操作的场景。
摘要由CSDN通过智能技术生成

一、程序、进程和线程

  1. 程序:为了完成一个任务,用某种语言编写的指令集和,即一段静态代码。
  2. 进程:是在工作运行中的程序。进程是有生命周期的;进程作为资源分配的单元,系统在运行时为每个进程分配不同的内存区域。
  3. 线程:进程可以进一步划分为线程,是一个程序的内部路径。若一个进程同一时间并行指向多个线程,就是支持多线程;线程作为调度和执行的单位,每个线程都拥有独立的运行栈和程序计数器;一个进程中的多个线程共享相同的内存地址空间,它们从同一个堆中分配对象,可以访问相同的变量及对象。

一般来说java应用程序至少有三个线程:main()主线程,gc()垃圾回收线程以及异常处理线程。

二、并行、并发、多线程优点

  1. 并行:多个CPU同时执行多个任务。
  2. 并发:一个CPU同时执行多个任务(相当于在任务之间快速切换)。
  3. 多线程优点
    可以提高应用程序的响应;
    提高CPU利用率;
    改善程序结构。
  4. 何时需要多线程
    程序需同时执行多个任务;
    程序需要实现一些需要等待的任务,如用户输入、文件读写操作、网络操作、搜索等。
    需要一些后台运行程序。

三、多线程的创建方式

1. 继承thread类,重写run()方法:

//多线程创建方法一:
// 1.创建一个继承Thread类的子类
class MyThread extends Thread{
    //2.重写run方法
    @Override
    public void run() {
        for(int i = 0; i < 100 ;i++){
            //打印当前线程名称
            System.out.println(this.getName() + ":" +i);
        }
    }
}
public class TreadTest {
    public static void main(String[] args) {
        //3.创建子类对象并调用start()方法开启线程
        MyThread t1 = new MyThread();
        t1.start();//开启第一个线程

        MyThread t2 = new MyThread();
        t2.start();//开启第二个线程

        System.out.println("hello");//主线程
    }
}

结果如下图所示:其结果并不唯一,线程一和线程二。

在这里插入图片描述
继承thread()类有个缺点:无法再继承其它类。因此有了第二种线程创建方法实现Runnable()接口。

2.实现Runnable()接口,重写run()方法:

//创建方式二:实现Runnable()接口
class myThread implements Runnable{
    @Override
    public void run() {
        for(int i = 0;i < 50;i++){
            //不能使用this.getName()得到当前线程了
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}
public class TreadTest1 {
    public static void main(String[] args) {
        //创建线程对象,把实现了Runnable接口的对象作为参数传入;
        myRunnable m1 = new myRunnable();
        Thread t1 = new Thread(m1);

        myRunnable m2 = new myRunnable();
        Thread t2 = new Thread(m2);
        //启动两个线程
        t1.start();
        t2.start();

        System.out.println("hello");
    }
}

执行结果如下,与第一种方式实现效果是一样的,线程一和线程二抢占式执行。
在这里插入图片描述
由于 前两种创建方式都无返回值,因此有了第三种线程创建方式。
3.实现callable接口,重写call()方法:

//创建多线程方法三:继承Callable方法
class MyCallable implements Callable{
    //重写call()方法
    @Override
    public Object call() throws Exception {
        for(int i = 0;i < 50;i++){
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
        return 0;
    }
}
public class ThreadTest3 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建callable对象
        MyCallable c1 = new MyCallable();
        MyCallable c2 = new MyCallable();
        //创建执行任务
        ExecutorService s = Executors.newFixedThreadPool(2);
        //提交执行任务得到future对象
        Future<Integer> f1 = s.submit(c1);
        Future<Integer> f2 = s.submit(c2);
        //得到返回结果
        int num1 = f1.get();
        int num2 = f2.get();
    }
}

运行结果如下:
在这里插入图片描述
四、线程创建方法比较

  1. 继承Thread类编程比较简单,可以通过this.的方式获取该线程名儿,且多个线程可以使用同一份数据资源,但是继承该Thread类后就无法继承其他类。
  2. 实现Runnable()接口和Callable()接口编程比较复杂,访问当前线程名需调用Thread.currentThread()方法,适合多个线程处理同一份资源,Callable()比Runnable()多了一个返回值的功能。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值