多线程是什么

运行一个程序叫做一个线程,运行过程中时处理多个任务,这些任务叫做线程(比如同时播放画面和声音)
注:真正的多线程需要多核CPU同时处理多个线程,单核的是伪多线程(单核同一时间只能处理一个线程,但是线程之间切换很多,毫秒级,所以看起来像是在同时处理)

一、继承类Thread
  1. 创建一个类TestThread
  2. 继承父类Thread
  3. 重写方法Run
  4. new对象TestThread
  5. 开启多个线程对象名.start()
public class TestThread extends Thread {

    @Override
    public void run(){
        //输出当前线程的名字        
        System.out.println(Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        //创建三个线程
        TestThread t1 = new TestThread();
        TestThread t2 = new TestThread();
        TestThread t3 = new TestThread();
        
        //线程开始
        t1.start();
        t2.start();
        t3.start();
    }
}

结果如下

<!---->
Thread-0
Thread-2
Thread-1

Process finished with exit code 0
//从结果可以看出,这3个线程不是按照顺序依次执行的
二、实现接口Rubbable
  1. 创建一个类TestRunnable
  2. 实现接口Runnable
  3. 重写方法Run
  4. new对象TestRunnable
  5. 开启多个线程new Thread(对象名,线程名).start()

完整代码如下

public class TestRunnable implements Runnable {

    //重写run方法
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }

    //测试
    public static void main(String[] args) {
        TestRunnable t = new TestRunnable();

        //线程开启
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
    }
}

运行结果如下:

<!---->
Thread-0
Thread-2
Thread-1

Process finished with exit code 0

//从结果可以看出,这3个线程不是按照顺序依次执行的
三、实现接口Callable

这个接口使用了线程池

  1. 写一个类TestCallable实现接口Callable
  2. 重写方法call(),方法类型自定义(可以是Boolean或Integer,但是不能是void)要有返回值return
  3. 创建new多个TestCallable
  4. 开启线程池Executors.newFixedThreadPool(线程数)
  5. 线程执行
  6. 关闭线程池

完整代码如下


import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestCallable implements Callable {

    public Boolean call() throws Exception {
        System.out.println(Thread.currentThread().getName());
        return true;
    }

    public static void main(String[] args) {
        TestCallable t1 = new TestCallable();
        TestCallable t2 = new TestCallable();
        TestCallable t3 = new TestCallable();
        TestCallable t4 = new TestCallable();

        //创建任务的线程池,任务数>=我们要跑的线程
        ExecutorService ser = Executors.newFixedThreadPool(4);

        //线程执行
        ser.submit(t1);
        ser.submit(t2);
        ser.submit(t3);
        ser.submit(t4);
        //关闭线程
        ser.shutdown();
    }
}

运行结果如下

<!---->
pool-1-thread-1
pool-1-thread-3
pool-1-thread-2
pool-1-thread-4

Process finished with exit code 0

//从结果可以看出,这几个线程不是按照顺序依次执行的

使用线程池的好处:

降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

提高响应速度:当任务到达时,可以不需要等待线程创建就能立即执行。

提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,监控和调优。