ThreadPoolExecuto 线程池 最深刻理解

1. 线程池的理解:

为什么需要线程池: 线程可以复用,线程任务执行完毕以后,cpu 调度 以后可以复用,不用频繁创建开启线程

代码1:

public class Main2 {
	
	 public static void main(String[] args) throws InterruptedException {
		 /*   参数1:核心线程数,默认启动线程数
	         *   参数2: 最大启动线程数
	         *   参数3,参数4, 线程不够的时候,启动的线程,如果60s 内没有在次执行Runnable,那么 被回收
	         *   参数5: 如果任务超过最大线程数,没有对应的线程来执行,那么放入队列中
	         */
       ExecutorService executorService =
       new ThreadPoolExecutor(1, 2,60, TimeUnit.SECONDS,new LinkedBlockingDeque<Runnable>(3));
       for (int i = 0; i < 5; i++) {
    	   executorService.execute(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		System.out.println("线程:"+ Thread.currentThread().getName());
			}
		});
		
	}
	}
}

运行结果:正确执行

线程:pool-1-thread-1
线程:pool-1-thread-2
线程:pool-1-thread-1
线程:pool-1-thread-2
线程:pool-1-thread-1

如何理解上面代码:
  核心线程是1,有5个任务
 任务1交给核心线程执行,那么还有4个任务,
 阻塞队列长度是3,3个任务放入阻塞队列中,
 最大线程是2,那么还可以启动一个线程, 剩下的一个任务交给这个线程A执行,
 等核心线程  和 线程A执行完成任务,从队列中 取出 任务交替 执行

  代码2 :

public class Main2 {
	
	 public static void main(String[] args) throws InterruptedException {
		 /*   参数1:核心线程数,默认启动线程数
	         *   参数2: 最大启动线程数
	         *   参数3,参数4, 线程不够的时候,启动的线程,如果60s 内没有在次执行Runnable,那么 被回收
	         *   参数5: 如果任务超过最大线程数,没有对应的线程来执行,那么放入队列中
	         */
       ExecutorService executorService =
       new ThreadPoolExecutor(1, 2,60, TimeUnit.SECONDS,new LinkedBlockingDeque<Runnable>(3));
       for (int i = 0; i < 6; i++) {
    	   executorService.execute(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		System.out.println("线程:"+ Thread.currentThread().getName());
			}
		});
		
	}
	}
}

运行结果: 报错

Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.denganzhi.bb.Main2$1@70dea4e rejected from java.util.concurrent.ThreadPoolExecutor@5c647e05[Running, pool size = 2, active threads = 2, queued tasks = 3, completed tasks = 0]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
    at com.denganzhi.bb.Main2.main(Main2.java:22)
线程:pool-1-thread-1
线程:pool-1-thread-2
线程:pool-1-thread-1
线程:pool-1-thread-2
线程:pool-1-thread-1

如何理解上面代码:
  核心线程是1,有6个任务
 任务1交给核心线程执行,那么还有5个任务,
 阻塞队列长度是3,3个任务放入阻塞队列中,
 最大线程是2,那么还可以启动一个线程, 剩下的一个任务交给这个线程A执行,
 那么此时还有一个任务B,无法处理,报错.....
 前面5个任务,由核心线程  和 线程A执行完成任务,从队列中 取出 任务交替 执行

2.   系统API 提供线程池

//        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
//                60L, TimeUnit.SECONDS,
//                new SynchronousQueue<Runnable>());
        Executors.newCachedThreadPool();
  //  核心线程数是0 , 最大线程数 Integer.MAX_VALUE


// 核心线程数是 6 ,最大线程数是 6
        //        return new ThreadPoolExecutor(6, 6,
//                0L, TimeUnit.MILLISECONDS,
//                new LinkedBlockingQueue<Runnable>());
        Executors.newFixedThreadPool(6); 

  3. Callable  任务,返回值线程

callable的基本使用:

public class TestThread implements Callable<String> {

	@Override
	public String call() throws Exception {
	Thread.sleep(5000);
		return "ni hao";
	}

	public static void main(String[] args) throws InterruptedException, ExecutionException {
		TestThread tt= new TestThread();
		FutureTask<String> ft=new FutureTask<>(tt);
		Thread t= new Thread(ft);
		 // 启动线程
		t.start();
		System.out.println(System.currentTimeMillis());
		// 阻塞
		String str= ft.get();
		System.out.println(str);
		
	}
}

线程池中使用 Callable 通过 submit  阻塞,逐一执行,输出

public class TestThread{
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		 ExecutorService service= Executors.newFixedThreadPool(5);
		 for (int i = 0; i <10; i++) {
		Future<String> f=  service.submit(new Callable<String>() {

			@Override
			public String call() throws Exception {
		     	Thread.sleep(2000);
				return Thread.currentThread().getName();
			}
		});
		// 阻塞,逐一执行,输出
		 String str= f.get();
		 System.out.println(str);
		}
	 service.shutdown();

	}
}

把执行结果装入List ,一次输出5个线程执行结果:

public class TestThread{
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		 ExecutorService service= Executors.newFixedThreadPool(5);
		 List<Future> list=new ArrayList<Future>();
		 for (int i = 0; i <10; i++) {
		Future<String> f=  service.submit(new Callable<String>() {

			@Override
			public String call() throws Exception {
		     	Thread.sleep(2000);
				return Thread.currentThread().getName();
			}
		});
		// 阻塞,逐一执行,输出
		list.add( f);
		}
		 for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i).get());
		}

	}
}

 4.  Callable  源码分析

源码分析:

public class TestThread implements Callable<String> {

	@Override
	public String call() throws Exception {
	Thread.sleep(5000);
		return "ni hao";
	}

	public static void main(String[] args) throws InterruptedException, ExecutionException {
		TestThread tt= new TestThread();
		FutureTask<String> ft=new FutureTask<>(tt);
		Thread t= new Thread(ft);
		 // 启动线程
		t.start();
		System.out.println(System.currentTimeMillis());
		// 阻塞
		String str= ft.get();
		System.out.println(str);
		
	}
}

 源码分析: 
    FutureTask<String> ft=new FutureTask<>(tt);
        Thread t= new Thread(ft);
         // 启动线程
        t.start();   内部调用  FutureTask 的 run 方法 , 此时 state = NEW  就是 0 

public void run() {
// 此时 state  ==  NEW 
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
//这里 回调  线程中 重写的  call 方法
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
}

   set(result);

   protected void set(V v) {
    private static final int NEW          = 0;
    private static final int COMPLETING   = 1;
    private static final int NORMAL       = 2;
// 这里 state   从 0 - 1  -2  也就  state = COMPLETING  ->  NORMAL       
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
            finishCompletion();
        }
    }

    // 阻塞  内部死循环 
        String str= ft.get();

public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
// 这里死循环,返回 NORMAL  
            s = awaitDone(false, 0L);
        return report(s);
    }

// 返回 s  , 就是 f.get()的 返回值
 @SuppressWarnings("unchecked")
    private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

阻塞内部回调原理, 值得状态变化 : 

public class TestThread{
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		showA showa=new showA();
		showa.showGradle(new gradleA() {
			
			@Override
			public void showA() {
		       System.out.println("xxx");
			}
		});
	}
}
class showA{
	interface gradleA{
		void showA();
	}
	gradleA gradlaa;
	
	public void showGradle(	gradleA gradla) throws InterruptedException{
		for ( ; ; ) {
			Thread.sleep(3000);
			gradla.showA();
			return; 
		}
	}	
}

猜你喜欢

转载自blog.csdn.net/dreams_deng/article/details/108927505