java-多线程、线程池

本文详细介绍了Java中的多线程概念,包括进程与线程的区别,线程的三种状态以及创建线程的三种方式:继承Thread、实现Runnable接口和实现Callable接口。此外,还讲解了线程池的重要性和使用,如Executors工具类以及ThreadPoolExecutor的参数说明,强调了线程池在管理线程资源和提高效率方面的作用。
摘要由CSDN通过智能技术生成

java-多线程、线程池

什么是线程

  • 进程:并发执行的程序在一个数据集合上的执行过程,它由进程控制块、程序段、数据段3部分组成。进程之间的存储空间各自独立,一个进程可以包含若干线程。

  • 线程:在进程中并发地处理事件,和所属进程使用同一个存储空间,他有就绪、阻塞、运行3种状态。线程之间共享存储空间,线程可以创建和撤销另一个线程。

什么是多线程

假如你有一堆砖头,单线程情况下一个人去搬,多线程就是将砖头分多份,多个人同时搬。多线程是并发的,因此处理一件事情很快。

线程的3种状态

一个线程就是一个搬砖工人,在一个人搬砖的情况下:

  • 就绪:搬砖的人准备好开工了。
  • 阻塞:搬砖人类趴下了,就没人干了,这件事就停止了,也就是阻塞了。
  • 停止:砖搬完了,不用干了

阻塞是说单个线程的,多线程中每个线程都存在各自的3种状态。

3种:就绪、阻塞、停止
5种:新建、就绪、运行、阻塞、停止
7种:新建、就绪、运行、等待、阻塞、超时等待、停止

多线程的3种方式

你要执行的方法,然后我们使用不同方式来多线程执行。

public class Method{
    public void run() {
        System.out.println("方法1");
    }
}

1.继承Thread

线程类,实现父类 Thread

public class Thread1 extends Thread {
	//将调用方法的类传入线程类
    private Method method;
    public Thread1 (Method method){
        this.method=method;
    }

	//Thread.run来调用类方法
    @Override
    public void run() {
        method.run();
    }
}

创建线程:实际上调用Thread的start方法执行。

 public static void main(String[] args) {
 		//创建3个线程
        new Thread1(new Method()).start();
        new Thread1(new Method()).start();
        new Thread1(new Method()).start();
    }

2.实现Runnable接口

public class Thread2 implements Runnable {
	//传入方法类
    private Method method;
    public Thread2(Method method){
        this.method=method;
    }
	//使用接口的run方法来调用执行的方法
    @Override
    public void run() {
        method.run();
    }
}

测试
还是使用了Thread.start().

 public static void main(String[] args) {
 		//创建3个线程
        new Thread(new Thread2(new Method())).start();
        new Thread(new Thread2(new Method())).start();
        new Thread(new Thread2(new Method())).start();
 }

分析Runnable接口方式

首先你的线程类实现了Runnable接口,然后查看Thread类源码,发现它也是实现Runnable接口的。

此时我们进入:new Thread( Runnable runnable ),发现它调用了init方法,在init方法中将Runnable 类型的值交给了Thread的成员变量,简写如下:

public class Thread implements Runnable{
	//将自定义的线程类传入
	private Runnable target;
	public Thread(Runnable target){
		this.target=target;
	}
	// 下面这一段是Thread类中的原内容
	@Override
    public void run() {
        if (target != null) {
           target.run();		//调用自定义的线程类的run方法
        }
    }
   
}

如果你学过代理模式,你恐怕已经悟了,这不就是使用Thread类代理了你自定义的线程类吗?

同时可以知道:静态代理可以使继承父类变为实现接口。因为java不支持多继承,但支持多实现。

3.实现Callable<>接口

通常情况会使用Runnable来构建线程,但是它存在一个问题,就是无法获得返回值。

Callable接口可以返回值,泛型则是指返回值类型,即:Callable<返回值类型>.

线程类:

public class Thread3 implements Callable<String> {
    private Method method;
    public Thread3(Method method){
        this.method=method;
    }
    
    
    
    @Override
    public String call() throws Exception {
        this.method.run();
        return "线程创建成功!";
    }
}

测试:

public static void main(String[] args) throws ExecutionException, InterruptedException {
    FutureTask<String> task1=new FutureTask<> (new Thread3(new Method1()));
    FutureTask<String> task2=new FutureTask<> (new Thread3(new Method2()));
    FutureTask<String> task3=new FutureTask<> (new Thread3(new Method3()));
    
    new Thread(task1).start();
    new Thread(task2).start();
    new Thread(task3).start();
    task1.get();                //线程1返回值
}

其实FutureTask是Runnable的实现类,也实现了run方法,只不过是由FutureTask类来调用你的任务类,并在run方法中调用并获取返回值。


java线程池

当我们使用多线程时,需要创建多个线程并销毁它们,这个过程会消耗内存,而有时候我们直接创建线程是杂乱无章的,这样一来就会增加无意义的消耗。因此我们需要有一个统一管理这些线程的工具,这个工具就叫做线程池。

  • Executors :你可以理解为线程的工具类,为我们提供了很多写好的创建线程池的方法。
  • Executor:一个接口,所有线程池的根接口,只有一个execute()方法来执行线程。
  • ThreadPoolExecutor:创建线程的类,一般用它来创建自定义线程池,是Executor的实现类。

new ThreadPoolExecutor()

  • 参数1:线程池最小线程数
  • 参数2:线程池最大线程数
  • 参数3:线程存活时间
  • 参数4:存活时间的时间单位
  • 参数5:工作队列对象
  • 参数6:线程工厂,可缺省
  • 参数7:阻塞时的处理程序,可缺省。

创建好线程池后,调用线程池的execute() 方法来执行一个线程任务,参数为Runnable类型,(创建线程的三种方法都是Runnable接口的实现)。

使用线程池来开启多线程:
上面可以发现Executors类种提供多种线程池,自定义时要传多个参数,因此我们先用默认的线程池试一试:

public class MainExecutor  {
    public static void main(String[] args) {
        //使用Executors类的方法创建一个可以做定时任务的线程池
        Executor executor= Executors.newCachedThreadPool();
        //使用线程池启动3个线程
        executor.execute(new Thread1(new Method1()));
        executor.execute(new Thread1(new Method2()));
        executor.execute(new Thread1(new Method3()));
    }
}

线程池的种类还是要看队列是怎么用的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值