简谈多线程

简谈多线程

概念

多线程

多线程:在一个进程中可以同时开始多个线程,让这多个线程同一时间去执行某些任务或者功能,以此来提高执行效率。

进程;每个进程都有独立的代码和数据空间,一个进程中可以有1-n个线程。(进程是资源分配的最小单位)。

并行和并发

并行:多个任务在同一时刻点同时执行。

并发:多个任务在同一时间内分时执行线程。

多线程实现方法

1 继承Thread类

优点:编码简单

缺点:线程类继承了Thread,无法再继承其他类,不利于功能的扩展

子类代码:


//写一个子类继承Thread
public class MyThread extends Thread {
    // 重写run方法
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("MyThread" + i);
        }
    }

测试类代码:

//测试类
public class ThreadTest1 {
    public static void main(String[] args) {
        //创建线程对象
        MyThread myThread = new MyThread();
        //启动线程
        myThread.start();
        for (int i = 0; i < 5; i++) {
            System.out.println("main" + i);
        }
    }
}

测试结果:

for循环内容交叉打印输出
MyThread0
main0
MyThread1
main1
MyThread2
main2
MyThread3
main3
MyThread4
main4

2 实现Runnable 接口

优点:任务类只是实现了接口,可以继续继承其他类,实现其他接口,扩展性强

缺点:需要多一个Runnable对象,有结果不能直接返回

实现类代码:


//实现类实现Runnable接口
public class MyRunnable implements Runnable {
    //重写run方法
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Runnable"+i);
        }
    }
}

测试类代码:

public class Test01 {
    public static void main(String[] args)  {
        // 创建MyRunnable任务
        MyRunnable myRunnable = new MyRunnable();
        Thread mr = new Thread(myRunnable, "myRunnable");
        mr.start();
        //主线程
        for (int i = 0; i < 5; i++) {
            System.out.println("main" +i);
        }
    }
}

测试结果:

Runnable0
main0
Runnable1
main1
Runnable2
main2
Runnable3
main3
Runnable4
main4

3 实现Callable接口

优点:最大的优点就是可以返回线程执行完毕后的结果

缺点:编码复杂很多。

实现类代码:

public class Mycallable implements Callable<String> {
    int  n;
    public   Mycallable(int n){
        this.n=n;
    }
    @Override
    public String call() throws Exception {
        //计算数字的和
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum+=n;
        }
        //Thread.currentThread().getName() 获取线程的名字
        String result = Thread.currentThread().getName() + "求到的和是:" +sum;
        return result;
    }
}

4 创建线程池

4.1 使用ThreadPoolExecutor创建

优点:可以实时获取线程池内线程的各种状态,还可以动态的调整线程池的大小

测试类代码:

public class ThreadTest2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1.定义线程池对象
        ThreadPoolExecutor tp = new ThreadPoolExecutor(
                3,   //核心线程数
                5,              //最大线程数
                100,            //休闲存活时间
                TimeUnit.SECONDS, // 时间单位
                new ArrayBlockingQueue<>(3), //等待队列
                Executors.defaultThreadFactory(),  //创建工厂
                new ThreadPoolExecutor.AbortPolicy() //默认拒绝策略
        );
        // 2.创建任务对象
        Mycallable tc = new Mycallable(100);
        // 3.执行任务
        Future<String> f1 = tp.submit(tc); //如果是实现的Runnable接口,这里建议使用execute。    
        Future<String> f2 = tp.submit(new ThreadCallable(200));
        // 4.返回执行结果
        System.out.println(f1.get());
        System.out.println(f2.get());
    }
}

测试结果:

pool-1-thread-1求到的和是:10000
pool-1-thread-2求到的和是:19900
4.2 使用Executors的工具类创建线程

优点:创建简单

缺点:里面的最大线程数被设置为Integer.MAX_VALUE,可能会创建出大量的线程,导致OOM(内存溢出)

测试代码:

public class ThreadTest3 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //定义起来方便很多,但是限制也很多
        ExecutorService es = Executors.newFixedThreadPool(4);
        Future<String> f1 = es.submit(new Mycallable(300));
        Future<String> f2 = es.submit(new Mycallable(400));
        Future<String> f3 = es.submit(new Mycallable(500));
        Future<String> f4 = es.submit(new Mycallable(600));

        System.out.println(f1.get());
        System.out.println(f2.get());
        System.out.println(f3.get());
        System.out.println(f4.get());
    }
}

测试结果

pool-1-thread-1求到的和是:90000
pool-1-thread-2求到的和是:160000
pool-1-thread-3求到的和是:250000
pool-1-thread-4求到的和是:360000

多线程实现方式的区别

1,Thread和Runnable区别

Thread底层是Runnable的实现类,需要进行继承,扩展性不强

2,Runnable和Callable的区别

Runnable和Callable都是接口,但是Callable可以捕获处理异常信息并返回结果,Runnable不能抛出运行时的异常,且无法捕获处理异常。

线程池生命周期

状态总结:

1,NEW 新建

线程刚被创建,但是并未启动。

2,Runnable 可运行

线程已经调用了start(),等待CPU调度

3,Blocked 锁阻塞

线程在执行的时候未竞争到锁对象,则该线程进入Blocked状态;

4,Waiting 无限等待

一个线程进入Waiting状态,另一个线程调用notify或者notifyAll方法才能够唤醒

5,Timed Waiting 计时等待

同waiting状态,有几个方法(sleep,wait)有超时参数,调用他们将进入Timed Waiting状态。

6 ,Terminated 被终止

因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

生命周期图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z3fdFVMD-1690452355700)(C:\Users\13601\AppData\Roaming\Typora\typora-user-images\image-20230727180234014.png)]

g 无限等待

一个线程进入Waiting状态,另一个线程调用notify或者notifyAll方法才能够唤醒

5,Timed Waiting 计时等待

同waiting状态,有几个方法(sleep,wait)有超时参数,调用他们将进入Timed Waiting状态。

6 ,Terminated 被终止

因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

生命周期图:

在这里插入图片描述

本文只简单的说了一下多线程的部分内容,感谢各位大佬的观看,文中如有问题,请各位大佬多多斧正!!!再次感谢!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值