线程创建方式

一、继承Thread

1、概述:Thread是Runnable的实现类,核心方法是run()方法
2、代码实现

public class ThreadModeCreate extends Thread {
    @Override
    public void run() {
        System.out.println("执行了ThreadModeCreate的run方法");
        throw new RuntimeException("异常");
    }
}

//自定义线程异常捕获
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        // 处理异常的代码
        System.out.println(t.getName()+"------"+e.getMessage());
    }
}

class Test {
    public static void main(String[] args) {
        ThreadModeCreate threadModeCreate = new ThreadModeCreate();
        threadModeCreate.setName("线程创建方式一");
        MyUncaughtExceptionHandler handler = new MyUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(handler);
        //执行run方法
        threadModeCreate.start();
    }

}

3、简化版本通过lambda表达式事项

   new Thread(()->{
            try {
               //你要执行的方法
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"AA").start();

二、实现Runnable接口

public class RunnableModeCreate implements  Runnable
{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }

}
class TestRunnable{
    public static void main(String[] args) {
        //方式一
        RunnableModeCreate runnableModeCreate = new RunnableModeCreate();
        Thread thread = new Thread(runnableModeCreate);
        thread.start();
        //方式二
        new Thread(()->{
            System.out.println(Thread.currentThread().getName());
        }).start();
    }
}

三、通过callable和Future创建线程

Future:一个接口表示异步执行某个操作
Callable:一个接口,可以通过自定义实现类,实现call()方法;在多线程执行时可以获取线程的执行结果

class m2 implements Callable<String> {

    @Override
    public String call() throws Exception {
        Thread.sleep(2000);
        return Thread.currentThread().getName() + "通过Callable和Future";
    }
}

public class CallableExe {
    public static void main(String[] args) throws Exception {


//方法一
        m2 m = new m2();
        FutureTask<String> integerFutureTask = new FutureTask<String>(m);
        new Thread(integerFutureTask, "Future").start();
        //判断run方法是否执行完成
        while (!integerFutureTask.isDone()) {
//            System.out.println(Thread.currentThread().getName() + "…………wait");
        }
        String s = integerFutureTask.get();
        System.out.println(s);

//方法二
        //通过线程池实现
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //通过线程池执行该方法
        Future<String> future = executorService.submit(m);
        try {
            System.out.println("获取参数");
            //获取call的执行结果
            String callback = future.get();
            System.out.println(callback);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            //关闭线程池
            executorService.shutdown();
        }

    }
}

四、通过线程池实现

优点:
1、避免方法调用导致线程对象的频繁创建,增加资源的消耗
2、可以对线程的数量进行监控和调优,避免线程数量创建过多,销毁不及时导致内存溢出

创建线程池的方法

  1. 通过创建ThreadPoolExecutor对象自定义线程池
  2. Executors.newScheduledThreadPool(10); 定时线程池
  3. Executors.newCachedThreadPool();可缓存线程池
  4. Executors.newFixedThreadPool(10); 定长线程池
  5. Executors.newSingleThreadExecutor(); 单线程化线程池

自定义线程池参数:

corePoolSize:存活核心线程数,不会回收;除非设置allowCoreThreadTimeOut为true;才会超时回收;
maximumPoolSize:线程池所能容纳的最大线程数。当活跃线程数达到该数值后,后续的新任务将会阻塞。
keepAliveTime:当线程数大于核心线程,这是多余空闲线程超过这个时间将被回收;
unit:线程存活的时间单位;枚举TimeUnit【MILLISECONDS(毫秒)、SECONDS(秒)】
workQueue:任务队列。通过线程池的 execute() 方法提交的 Runnable 对象没有线程执行,就储存在该队列中;
threadFactory:线程工厂。用于指定为线程池创建新线程的方式
handler:拒绝策略,超过线程边界和队列容量如何处理该数据

        ArrayBlockingQueue delayQueue = new ArrayBlockingQueue(3);
        ThreadPoolExecutor callerRunsPolicy = new ThreadPoolExecutor(2, 2, 10, TimeUnit.MILLISECONDS, delayQueue);
        callerRunsPolicy.execute(() -> {
            try {
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

任务队列(workQueue)使用

1.ArrayBlockingQueue:数组阻塞队列

概述:一个由数组构成的有界阻塞队列;
实现:

        ArrayBlockingQueue delayQueue = new ArrayBlockingQueue(2, true);
        ThreadPoolExecutor callerRunsPolicy = new ThreadPoolExecutor(2, 2, 10, TimeUnit.MILLISECONDS, delayQueue);
        for (int i = 0; i < threadSize; i++) {
            callerRunsPolicy.execute(this.runnableTest());
        }
        BlockingQueue<Runnable> queue = callerRunsPolicy.getQueue();
        System.out.println(queue.size());
        callerRunsPolicy.shutdown();

注意: 当需要运行的线程数大于最大核心数时,存储到该队列中,当队列装不下时看最大线程数,如果最大线程数大于核心线程数;开新线程;如何线程池和队列都装满了,就需要考虑拒绝策略了;

2.LinkedBlockingQueue:链表阻塞队列

概述:一个由链表构成的有界阻塞队列;默认最大值MAX_VALUE:2^31 -1

3.DelayQueue:延迟无界队列

概述:一个无界延迟队列;时间没到任务取不出来;要对象实现Delayed接口,自定compareTo和getDelay方法;

4.PriorityBlockingQueue:优先级阻塞队列

概述:一个支持优先级排序的无界阻塞队列,实现Comparable接口,重写compareTo方法,自定义优先级规则;

5.SynchronousQueue

概述:Executors.newCachedThreadPool()创建的线程池使用的队列默认是SynchronousQueue。该队列不存储数据;
注:在使用该队列的take()和put()方法时会出现阻塞,因为put添加的数据没有被take()消费,put就会阻塞等待消费,如take()消费方法执行队列没有数据,take会阻塞等待put添加数据;如果put和take在同一个线程中执行会出现死锁

 new Thread(()->{
            try {
                System.out.println("开始添加数据");
                queue.put(1);
                System.out.println("put结束");
                queue.take();
                System.out.println("take结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
6.LinkedBlockingDeque

概述:基于链表创建的双向有界队列,默认边界是:最大值MAX_VALUE:2^31 -1

7.LinkedTransferQueue

概述:基于链表创建的无界阻塞队列,在线程池中作用等同于LinkedBlockingQueue

注: 有界队列和无界队列的区别;有界队列当队列饱和时,会执行最大线程池数;如何超过会执行拒绝策略;无界队列,任务队列永远都可以添加任务,所以maximumPoolSize 没有意义;

拒绝策略(handler)

当使用有界队列时,数据装不下,多余的数据就会走拒绝策略;jdk提供了以下四种拒绝策略;

1.AbortPolicy(默认):拒绝处理任务,并抛出异常RejectedExecutionHandler
2.CallerRunsPolicy:在调用线程中运行,除非该线程已关闭,在这种情况下,任务被丢弃
3.DiscardPolicy:直接丢弃不抛异常
4.DiscardOldestPolicy:丢弃队列最早的未处理任务(最先进入队列的任务),然后重新尝试执行任务。除非executor关闭,在这种情况下,任务将被丢弃

要想自己定义拒绝策略,实现RejectedExecutionHandler接口重写rejectedExecution()方法就行;
参考文献:https://blog.csdn.net/u013541140/article/details/95225769

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值