线程池Executor

1.两个线程交替输出1a2b3c4d......z

//解法一:LockSupport.park,unpart
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
t1 = new Thread(()->{
    for(char c : aI){
        System.out.print(c);
        LockSupport.unpark(t2); //叫醒t2
        LockSupport.park(); //T1阻塞
    }

}, name:"t1");

t2 = new Thread(()->{
    for(char c : aC){
        LockSupport.park(); //t2阻塞
         System.out.print(c);
        LockSupport.unpark(t1); //叫醒t1
    }

}, name:"t2");
//解法二:wait notify
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
new Thread(()->{
    synchhroninzed(o){  //wait,notify必须使用sync
        for(char c : aI){
            System.out.print(C);
            try{
                o.notify();
                o.wait(); //让出锁
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        o.notify();//必须,否则无法停止程序
    }
}, name:"t1").start();

new Thread(()->{
    synchhroninzed(o){
        for(char c : aC){
            System.out.print(C);
            try{
                o.notify();
                o.wait();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        o.notify();
    }
}, name:"t2").start();

2.线程池

Executor 线程池,有execute方法

ExecutorService实现了Executor接口,并进行拓展。实现了线程生命周期的内容。

ExecutorService有execute和submit方法,区别是execute方法马上执行,submit方法把任务扔给线程池,不管什么时候执行,线程池自己决定。submit异步提交任务,原线程正常执行。

3.Callable接口

Callable类似与Runnable,可以用线程来运行,不同的是Callable有返回值。

V call() throws Exception; //相当于Runnable 中的void run()方法

/**
* ExecutorService
*/
public static void main(String[] args)throws InterruptedException,ExecutionException{
        // NO.1
        FutureTask<Integer> task = new FutureTask<>(()->{
            TimeUnit.MILLISECONDS.sleep(500);
            return 1000;
        });  //new Callable(){Integer call();}

        new Thread(task).start();
        System.out.println(task.get());

        //NO.2
        ExecutorService service = Executors.newFixedThreadPool(5);
        Future<Integer> f = service.submit(()->{
                TimeUnit.MILLISECONDS.sleep(500);
        return 1;
    });
        System.out.println(f.get());
        System.out.println(f.isDone());
    }
/*
* Callable
*/
 public static void main(String[] args) throws ExecutionException, InterruptedException{
        Callable<String> c = new Callable(){
          @Override
          public String call() throws Exception{
              return "hello callable";
          }
        };

        ExecutorService service = Executors.newCachedThreadPool();
        Future<String> future = service.submit(c); //异步 future存储执行结果

        System.out.println(future.get()); //阻塞
        service.shutdown();

    }
public static void main(String[] args) throws InterruptedException, ExecutionException {
        /**
         *  FutureTask 即使future又是task,可以作为任务执行,执行结果放在FutureTask里面
         *  FutureTask实现了RunnableFuture, RunnableFuture实现了Runnable,Future<V>
         */


        FutureTask<Integer> task = new FutureTask<>(()->{
            TimeUnit.MILLISECONDS.sleep(500);
            return 1000;
        }); //new Callable(){Integer call();}
        new Thread(task).start();
        System.out.println(task.get());//阻塞
    }

Callable 类似Runnable,但有返回值

Future 存储执行的将来才会产生的结果

FutureTask Future + Runnable

4.ThreadPoolExecutor

ThreadPoolExecutor是ExecutorService的子类;

ExecutorService是Executor的子类;

线程池(线程们(指向线程队列)+ 任务们(指向任务队列))

参数:

corePoolSize:核心线程数,可以设置是否参与归还给操作系统

maxiumPoolSize:最大线程数

keepAliveTime:生存时间,超时将线程归还给操作系统

TimeUnit.SECONDS:生产时间的单位

new ArrayBlockingQueue<Runnable>(capacity:4): 任务队列

Executors.defaultThreadFactory():线程工厂

new ThreadPoolExecutor.DiscardOldestPolicy():拒绝策略

线程池忙,而且任务队列满,执行拒绝策略

拒绝策略:

Abort:抛异常

Discard:扔掉,不抛异常

DicardOldest:扔掉排队时间最久的

CallerRuns:调用者处理任务,谁调用的谁去执行该任务

自定义线程池:7个参数(编码规范推荐)

 public static void main(String[] args) {
        ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(4), //阻塞队列
                Executors.defaultThreadFactory(), //线程工厂
                new ThreadPoolExecutor.DiscardOldestPolicy());//拒绝策略

        for (int i = 0; i< 8; i++){
            tpe.execute(new Task(i));
        }

        System.out.println(tpe.getQueue());

        tpe.execute(new Task(100));

        System.out.println(tpe.getQueue());

        tpe.shutdown();
    }

DefaultThreadFactory里面默认设置了:

线程的名字:namePrefix + threadNumber.getAndIncrement()  //方便出错回溯

                    namePrefix = "pool"+poolNumber.getAndIncrement()+"-thread-";

非守护线程:t.setDaemon(false)

线程优先级:t.setPriority(Thread.NORM_PRIORITY)

==================================================================

以上来自马士兵视频:高并发编程。个人学习笔记

上一篇:Callable入门 多线程的D3种实现方式


下一篇:【Java并发】FutureTask-Callable设置接口超时限制