5-2 Java线程

线程

进程与线程

  • 进程是系统资源分配的基本单位,线程是处理机调度的基本单位。
  • 一个进程至少包含一个线程,比如java中运行main方法的主线程。
  • 多线程是在一个程序中同时运行多个子任务。
  • 多线程可以更好地利于系统资源,提高处理机利用率。

线程的五种状态

在这里插入图片描述

  • 新建状态(New):线程对象创建后,即进入新建状态;
  • 就绪状态(Runnable):当调用线程对象的start()方法,线程进入就绪状态。处于就绪状态的线程,只是说明该线程已经做好了准备,随时等待CPU调度执行,并不是说执行了start()该线程就会立即执行;
  • 运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才开始执行,即进入运行状态。注意,就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
  • 阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态。直到其重新进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。
    根据阻塞产生的原因不同,阻塞状态又可以分为3种:
  1. 等待阻塞:运行状态中的线程执行Object.wait()方法
  2. 同步阻塞:线程在获取synchronized内部锁失败(因为锁被其它线程所占用)
  3. 其它阻塞:通过调用线程的Thread.sleep()、join()方法或发出I/O请求时,线程会进入到阻塞状态。当sleep()状态超时(sleep休眠结束)、join()等待线程终止或超时、或者I/O处理完毕时,线程重新转入就绪状态
  • 死亡状态(Dead):线程执行完毕或者因异常退出了run()方法,该线程结束生命周期,线程销毁。

线程相关方法

  • Object提供的方法:
  1. wait()

  2. notify()

  3. notifyAll()

  • Thread提供的方法:
  1. start()

  2. join()

  3. yield()
    让出处理机

  4. sleep()
    传入参数:指定睡眠时间(ms、[ns])
    使正在执行的线程让出处理机,进入等待状态睡眠一段时间,但是不会释放同步资源锁
    睡眠结束后线程会进入就绪状态

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(){
        @Override
        public void run() {
            System.out.println("t1");;
        }
    };
    t1.sleep(100);
}

创建线程的方式

  1. 继承Thread类
  2. 实现Runnable接口
  3. 构造FutureTask
    1)自定义一个类实现Callable接口并实现其中的call()方法来创建线程任务(Callable的call方法类似于Runnable的run方法)
    2)接着把这个线程任务以参数的形式传递给FutureTask,并new出一个FutuerTask对象
    3)最后将这个FutureTask对象继续以参数的形式传递给Thread
  4. 通过线程池创建

线程池

  • 推荐直接使用ThreadPoolExecutor,不使用Executors
ThreadPoolExecutor
构造
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
{...}
  • corePoolSize:核心线程数,线程池中至少有 corePoolSize 个线程可用或在运行。
  • maximumPoolSize:最大线程数,当等待队列装满的时候,线程池将线程数目扩充到 maximumPoolSize 个。
  • keepAliveTime:存活时间,核心线程外的线程,空闲时间超过 keepAliveTime 后才会被销毁。
  • unit:keepAliveTime的时间单位。
  • workQueue:等待队列。
  • threadFactory:线程工厂,用于创建新线程。
  • handler:拒绝策略,线程池满后,对新任务的应对策略。
execute() 与 submit()
  • execute():单纯的提交,无返回值,不能确定任务执行成功与否。
public class Main {
    private static final String templateS = "Thread %s starts.";
    private static final String templateE = "Thread %s starts.";

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                10,
                3,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(30),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        for(int i = 0; i < 10; i++){
            executor.execute(()->{
                String name = Thread.currentThread().getName();
                System.out.println(String.format("Thread: %s, start: %s", name, new Date()));
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(String.format("Thread: %s, end  : %s", name, new Date()));
            });
        }

        executor.shutdown();
        while (!executor.isTerminated()){

        }
        System.out.println("finished");

    }

}
  • submit():返回一个Future对象,可通过该对象获取返回值以及判断任务执行成功与否。
CompletableFuture
import java.util.concurrent.*;
import java.util.function.Consumer;

public class MyCompletableFuture {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        ExecutorService threadPool = Executors.newFixedThreadPool(3);

        ExecutorService threadPool = new ThreadPoolExecutor(
            5,
            10,
            3,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(10),
            new ThreadPoolExecutor.CallerRunsPolicy()
        );

        CompletableFuture.supplyAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thread1: " + Thread.currentThread().getName());
            return "t1";
        }, threadPool).whenComplete((v, e)->{
            if(e == null){
                System.out.println(Thread.currentThread().getName() + " value: " + v);
            }
        }).exceptionally((e)->{
            System.out.println(Thread.currentThread().getName());
            e.printStackTrace();
            return "exception";
        });
        System.out.println(Thread.currentThread().getName() + " == main");
        threadPool.shutdown();

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值