一、概念

进程:

进程是资源(CPU,内存等)分配的基本单位,它是程序执行的一个实例。
程序运行时就会创建一个进程,并为他分配资源,然后将创建的进程放入进程就绪队列中。
进程调度器选中它的时候就会为它分配CPU时间,程序开始真正的运行。

线程:

线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位。
一个进程可以由多个线程组成,线程之间共享进程的所有资源,每个线程都有自己的堆栈和局部变量。
线程由CPU独立调度执行,多个线程同时执行就可以实现并发操作。

通俗解释:

比如一个取款的功能,那么这个功能就相当于一个进程,而多个同时取款,每个人都会有一个请求,而每个请求都会分配一个线程来处理。

二、线程的五个状态

新建 ------ 就绪 ------ 运行 -------- 阻塞 ----- 消亡

三、 线程的创建

1.继承Thread类并重写run方法

public class ThreadDemo1 {
    public static class MyThread1 extends Thread{
        @Override
        public void run() {
            System.out.println("MyThread1 is running");
        }
    }
    //使用
    @Test
    public  void testOne() {
        //继承Thread类写法
        new MyThread1().start();
    }
}

2.实现Runable接口

public class ThreadDemo1 {
    public static class MyThread2 implements Runnable {

        @Override
        public void run() {
            System.out.println("MyThread2 is running");
        }
    }
    
    @Test
    public  void testOne() {
        //实现Runable接口写法
        MyThread2 thread2 = new MyThread2();
        new Thread(thread2).start();

        //实现Runable接口写法,使用匿名内部类创建线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("thread3 is running");
            }
        }).start();
        
        //实现Runable接口写法,使用java8新特性,函数式编程创建线程
        new Thread(() ->{
            System.out.println("thread4 is  running");
        }).start();
    }
}

3.实现Callable接口

Callable一般是配合线程池工具ExecutorService来使用。

public class ThreadDemo1 {
    public static class MyCallAble implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            Thread.sleep(1000);
            return 2;
        }
    }

    @Test
    public void testTwo() throws ExecutionException, InterruptedException {
    	//创建ExecutorService实例
        ExecutorService service = Executors.newCachedThreadPool();
        MyCallAble  callAble = new MyCallAble();
        //通过ExecutorService的submit方法来执行线程
        Future<Integer> future = service.submit(callAble);
        System.out.println(future.get());
    }
}

Callable方法创建的线程执行完毕后会返回一个Future接口的实例,可以通过该实例做一些线程的操作。
Future接口只有几个简单的方法。如下所示,通过方法名应该能知道什么意思,就不写注释了。

public abstract interface Future<V> {
    public abstract boolean cancel(boolean paramBoolean);
    public abstract boolean isCancelled();
    public abstract boolean isDone();
    public abstract V get() throws InterruptedException, ExecutionException;
    public abstract V get(long paramLong, TimeUnit paramTimeUnit)
            throws InterruptedException, ExecutionException, TimeoutException;
}

cancel方法是试图取消一个线程的执行。
注意是试图取消,并不一定能取消成功。存在取消失败的可能。boolean类型的返回值是“是否取消成功”的意思。参数paramBoolean表示是否采用中断的方式取消线程执行

四、相关类理解

1.FutureTask类

上面介绍了Future接口。这个接口有一个实现类叫FutureTask。FutureTask是实现的RunnableFuture接口的,而RunnableFuture接口同时继承了Runnable接口和Future接口:
RunnableFuture接口代码 如下:

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

FutureTask类里面实现了Future接口中cancle,isDone,get等方法的具体内容。

FutrueTask类的使用方法如下:

public class ThreadDemo1 {
    public static class TestFutureTask implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            Thread.sleep(1000);
            return 2;
        }
    }
    @Test
    public void testThree() throws ExecutionException, InterruptedException 		  {
        ExecutorService service = Executors.newCachedThreadPool();
        FutureTask<Integer> task = new FutureTask<>(new TestFutureTask());
        service.submit(task);
        System.out.println(task.get());
    }
}

解释:

FutureTask在 使用上和前面的Future方法还是有点区别的,

首先获取返回值是通过FutureTask的实例去获取的,

启动线程是service.submit(task);也是有返回值的,返回一个Future实例,但是 通过Future实例去获取线程的返回值是null。如下图所示

JAVA一个线程独享一个CPU 一个线程可以创建_System


注意:有文章说在很多高并发的情况下,

FutureTask task = new FutureTask<>(new TestFutureTask());这一句可能有问题

Callable的实现类TestFutureTask会被创建多个实例,FutureTask也可能会创建多个实例。

但是FutureTask能够在高并发的环境下确保线程的任务只执行依次。

这里我没有验证,有机会验证一下。