Java 多线程

线程

  • 线程是轻量级子进程,是最小的处理单元
  • 线程只能启动一次,第二次会IllegalThreadStateException
  • start()而不是run()

线程状态

在这里插入图片描述

import java.util.concurrent.TimeUnit;

public class ThreadStateDemo {

    private int i = 10;

    public static void main(String[] args) throws InterruptedException {
        waitDemo();
        final ThreadStateDemo stateDemo = new ThreadStateDemo();
        // NEW 新创建的线程
        final Thread thread = new ThreadState(stateDemo);
        // RUNNABLE 可以运行了
        System.out.println("thread.getState() = " + thread.getState());
        thread.start();
        System.out.println("thread.getState() = " + thread.getState());
        final Thread thread2 = new ThreadState(stateDemo);
        thread2.start();
        TimeUnit.SECONDS.sleep(2);
        // BLOCKED  获取锁失败
        System.out.println("thread2.getState() = " + thread2.getState());
        TimeUnit.SECONDS.sleep(200);
        // TERMINATED
        System.out.println("thread.getState() = " + thread.getState());
    }

    /**
     * 演示WAITING
     *
     * @throws InterruptedException
     */
    static void waitDemo() throws InterruptedException {
        final ThreadStateDemo stateDemo = new ThreadStateDemo();
        // 死循环减少i
        final Thread cut1 = new ThreadStateCut(stateDemo);
        final Thread cut2 = new ThreadStateCut(stateDemo);
        cut1.start();
        cut2.start();
        TimeUnit.SECONDS.sleep(11);
        System.out.println("cut1 = " + cut1.getState());
        System.out.println("cut2 = " + cut2.getState());

        // 增加i
        final Thread add = new ThreadStateAdd(stateDemo);
        add.start();
        TimeUnit.SECONDS.sleep(2);
        System.out.println("cut1 = " + cut1.getState());
        System.out.println("cut2 = " + cut2.getState());

        TimeUnit.SECONDS.sleep(20);

        System.exit(1086);
    }

    public synchronized void print() {
        try {
            TimeUnit.SECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " is run;");
    }

    public synchronized void intCut() {
        try {
            if (i >= 0) {
                TimeUnit.SECONDS.sleep(1);
                i--;
                System.out.println(Thread.currentThread().getName() + i + "-- 了");
            } else {
                //                wait();
                wait(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    public synchronized void intAdd() {
        i += 10;
        notifyAll();
    }

}

class ThreadState extends Thread {

    private final ThreadStateDemo print;


    ThreadState(ThreadStateDemo print) {this.print = print;}

    @Override
    public void run() {
        print.print();
    }
}

class ThreadStateCut extends Thread {

    private final ThreadStateDemo print;


    ThreadStateCut(ThreadStateDemo print) {this.print = print;}

    @Override
    public void run() {
        while (true) {
            print.intCut();
        }
    }
}

class ThreadStateAdd extends Thread {

    private final ThreadStateDemo print;


    ThreadStateAdd(ThreadStateDemo print) {this.print = print;}

    @Override
    public void run() {
        print.intAdd();
    }


}

Runnable

  • 实现Runnable
  • 实现run()方法

Thread

  • 继承Thread
  • 重写run()方法

Callable

  • 实现Callable
  • 实现call()方法
  • 有返回值
  • 可以将异常抛出
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

public class MultiThread {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println(Thread.currentThread().getName() + " is run;");
        // 继承Thread
        final Thread thread1 = new MyThread();
        thread1.start();
        // 实现Runnable
        final Thread thread2 = new Thread(new MyRunnable());
        thread2.start();
        //实现 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。
        final FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
        final Thread thread3 = new Thread(futureTask);
        thread3.start();
        // 获取计算的结果
        // get方法会阻塞,直到计算完成
        System.out.println(futureTask.get());

    }
}

class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " is run;");
    }
}

class MyRunnable implements Runnable {

    @Override
    public void run() {
      	try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " is run;");
    }
}

class MyCallable implements Callable<String> {

    @Override
    public String call() throws Exception {
        TimeUnit.SECONDS.sleep(1);
        return Thread.currentThread().getName() + " is run;";
    }
}

线程池

ThreadPoolExecutor

  • worker:工作线程,干活的
  • workQueue:任务队列
  • rejectedExecutionHandler:任务超出线程池负载时,如何处理
  • corePoolSize :核心线程数
  • maximumPoolSize:线程数量最大值
  • keepAliveTime:空闲线程存活时间(空闲且超出corePoolSize部分)
  • ThreadFactory:自定义创建线程的工厂类

基本状态

  • isShutdown 调用 shutdown 或者 shutdownNow
  • isTerminaed 所有任务都已经关闭
    在这里插入图片描述

提交任务基本流程

在这里插入图片描述

rejectedExecutionHandler 拒绝策略

  • AbortPolicy策略:该策略会直接抛出异常,阻止系统正常工作
  • CallerRunsPolicy策略:如果线程池的线程数量达到上限,该策略会把任务队列中的任务放在调用者线程当中运行
  • DiscardOledestPolicy策略:该策略会丢弃任务队列中最老的一个任务,也就是当前任务队列中最先被添加进去的,马上要被执行的那个任务,并尝试再次提交
  • DiscardPolicy策略:该策略会默默丢弃无法处理的任务,不予任何处理

ScheduledThreadPoolExecutor

  • 继承了ThreadPoolExecutor
  • schedule scheduleAtFixedRate等方法,延迟或者是定时执行任务
  • Timer更好

ForkJoinPool

  • ForkJoinTask:执行的任务,可以拆分fork()和合并结果join()
    • 有返回值 RecursiveTask
    • 无返回值 RecursiveAction
  • workQueue:变为双端队列,自身LIFO获取任务,其他worker 可以FIFO窃取任务

Executors 中的线程池

类型描述
newCachedThreadPool可以自动扩容的线程池,可以重复利用空闲的线程
newFixedThreadPool固定数量线程池
newSingleThreadExecutor一个线程的线程池
newScheduledThreadPool定时执行任务的线程池,替代Timer
newWorkStealingPool按CPU核心数创建的ForkJoinPool
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.LongStream;

public class ThreadPoolDemo {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 单个线程
        final ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        // 固定数量线程
        final ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
        // 可以自动扩容的线程池
        final ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        // 定时执行线程池
        final ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(3);
        // 窃取队列线程池-默认系统可用处理器数量
        // 多CPU计算机上处理性能更佳
        final ForkJoinPool newWorkStealingPool = (ForkJoinPool) Executors.newWorkStealingPool(3);


        // 延迟1秒,每2秒执行一次
        newScheduledThreadPool.scheduleAtFixedRate(new MyRunnable(), 1, 2, TimeUnit.SECONDS);
        // 提交任务 到 ForkJoinPool
        final ForkJoinTask<Long> forkJoinTask = newWorkStealingPool.submit(new MyRecursiveTask(0, 1000));
        // java 8 parallel 并行流
        final long longReduce = LongStream.rangeClosed(0, 1000L).parallel().reduce(0, Long::sum);
        System.out.println("longReduce = " + longReduce);
        System.out.println("forkJoinTask = " + forkJoinTask.get());

        for (int i = 0; i < 10; i++) {
            // 线程2 执行较慢。其他线程会窃取他的任务,多执行
            newWorkStealingPool.execute(new MyRunnable());
            // 延迟2秒后执行
            newScheduledThreadPool.schedule(new MyRunnable(), 2, TimeUnit.SECONDS);
            // 每次都创建新的线程
            newCachedThreadPool.execute(new MyRunnable());
            // 固定数量线程
            newFixedThreadPool.execute(new MyRunnable());
            //单一线程
            singleThreadExecutor.execute(new MyRunnable());
        }
        TimeUnit.SECONDS.sleep(5);
        for (int i = 0; i < 10; i++) {
            // 复用 线程池中空闲的线程
            newCachedThreadPool.execute(new MyRunnable());
        }
    }
}

class MyRecursiveTask extends RecursiveTask<Long> {
    private final int from;
    private final int to;

    public MyRecursiveTask(int from, int to) {
        this.from = from;
        this.to = to;
    }

    @Override
    protected Long compute() {
        if (to - from < 6) {
            long total = 0;
            for (int i = from; i <= to; i++) {
                total += i;
            }
            return total;
        } else {
            // 否则,把任务一分为二,递归拆分(注意此处有递归)到底拆分成多少分 需要根据具体情况而定
            int middle = (from + to) / 2;
            MyRecursiveTask taskLeft = new MyRecursiveTask(from, middle);
            MyRecursiveTask taskRight = new MyRecursiveTask(middle + 1, to);
            taskLeft.fork();
            taskRight.fork();
            return taskLeft.join() + taskRight.join();
        }
    }
}
class MyRunnable implements Runnable {

    @Override
    public void run() {
        try {
            if (Thread.currentThread().getName().contains("2")) {
                // 线程 2 多睡眠1秒
                TimeUnit.SECONDS.sleep(1);
            }
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " is run;");
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值