第一章:多线程与并发基础知识

1、线程状态转换

Thread.State 源码:(6个状态)

public static enum State {
        NEW,
        RUNNABLE,
        BLOCKED,
        WAITING,
        TIMED_WAITING,
        TERMINATED;

        private State() {
        }
    }
  • NEW(新建):当线程对象被创建但还未启动时,处于这个状态。即线程对象已经通过new关键字创建,但还没有调用其 start()方法。

  • RUNNABLE(可运行):当线程被start()方法启动后,处于这个状态。表示线程正在Java虚拟机中运行或准备运行。当线程获得了 CPU 执行权时,就可以从 Runnable 状态进入到 Running 状态。

  • BLOCKED(阻塞):当线程因为某些原因无法获得所需的锁资源时,处于这个状态。例如,如果一个线程正在执行同步代码块,并且另一个线程试图获取相同的锁,那么该线程将被阻塞,直到持有锁的线程释放锁。

  • WAITING(等待):当线程处于等待状态时,表示线程暂时停止执行,直到其他线程显式地唤醒它。 ①线程可以通过调用 wait() 方法进入等待状态(若需要退出等待,唤醒线程需调用 notify()notifyAll() );②线程通过 Thread.join() 方法等待其他线程结束。在这种状态下,线程不会占用 CPU 资源。

  • TIMED_WAITING(计时等待):与 Waiting 状态类似,但是可以指定等待的时间。线程可以通过调用带有超时参数的 wait() 方法、sleep() 方法或 join() 方法来进入计时等待状态。

  • TERMINATED(终止):当线程的 run() 方法执行完毕或者出现异常时,线程进入终止状态。一旦线程进入终止状态,它就不可再次启动。

Waiting / Timed Waitiing

进入等待退出方法
没有设置 Timeout 参数的 Object.wait() 方法Object.notify() / Object.notifyAll()
Thread.sleep() 方法时间结束
设置了 Timeout 参数的 Thread.join() 方法时间结束 / 被调用的线程执行完毕

2、实现线程入门类和接口

  • 实现 Runnable 接口 ; 无返回值
  • 继承 Thread 类 ; 无返回值
  • 实现 Callable 接口 ,结合 FutureFutureTask 使用 ; 有返回值

2.1、实现 Runnable 接口

需要实现 run() 方法。

Runnable 是一个函数式接口,在此使用 Java8 的函数式编程 创建了一个线程

  new Thread(() -> {
            log.info("Gao使用Java8 函数式编程,创建了一个线程.....");
        }).start();

2.2、继承Thread类

因为 Thread 类也实现了 Runable 接口,所以同样需要实现 run() 方法

当调用 start()方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调用,当一个线程被调度时会执行该线程的 run() 方法。

@Slf4j
public class ThreadUtil extends Thread {

    @Override
    public void run() {
        log.info("Gao 继承了Thread,创建了一个线程.....");
    }

    public static void main(String[] args) {
        new ThreadUtil().start();
    }

}

列举 Thread 类中的常用方法

  • currentThread() :静态方法,返回对当前正在执行的线程对象的引用;
  • start() :开始执行线程的方法,java虚拟机会调用线程内的run()方法;
  • yield() :指的是当前线程愿意让出对当前处理器的占用。注意:就算当前线程调用了yield()方法,程序在调度的时候,也还有可能继续运行这个线程的;
  • sleep() :静态方法,使当前线程睡眠一段时间;
  • join() :使当前线程等待另一个线程执行完毕之后再继续执行,内部调用的是Object类的wait方法实现的;

2.3、实现Callable接口

Runnable 相比,Callable 可以有返回值,而且支持 泛型

@Slf4j
public class ThreadUtil implements Callable {

    @Override
    public Object call() throws Exception {
        return " 实现Callable 接口.......";
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService pool = Executors.newCachedThreadPool();
        ThreadUtil threadUtil = new ThreadUtil();
        Future future = pool.submit(threadUtil);
        // 注意调用get方法会阻塞当前线程,直到得到结果。
        System.out.println(future.get());
    }

}

2.4、Future 接口

Future 接口中只有几个简单的方法:

public interface Future<V> {
    boolean cancel(boolean var1);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException, ExecutionException;

    V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException;
}

cancel() : 方式是试图取消一个线程的执行(是试图取消,并不一定取消成功),参数 paramBoolean 表示是否采用中断的方式取消线程执行。

2.5、FutureTask类

FutureTask 是实现的 RunnableFuture 接口,而 RunnableFuture 接口同时继承了 Runnable 接口和 Future 接口;固 FutureTaskFuture 的一个实现类。

@Slf4j
public class ThreadUtil implements Callable {

    @Override
    public Object call() throws Exception {
        return " 实现Callable 接口.......";
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService pool = Executors.newCachedThreadPool();
        ThreadUtil threadUtil = new ThreadUtil();
        FutureTask task = new FutureTask<>(threadUtil);
        pool.submit(task);
        // 注意调用get方法会阻塞当前线程,直到得到结果。
        System.out.println(task.get());
    }

}

上述代码示例与 Future 的代码示例有着略微的区别:

  • 此处调用 submit 方法是没有返回值的。实际上是调用的 submit(Runnable task) 方法,而上面的 Future 代码示例,调用的是 submit(Callable<T> task) 方法
  • FutureTask 直接取 get() 取值,而上面的 Future 代码示例是通过 submit() 方法返回的 Future 去取值

在很多高并发的环境下,有可能Callable和FutureTask会创建多次。FutureTask能够在高并发环境下确保任务只执行一次

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值