多线程技术讲解---持续更新

多线程技术讲解

传统线程技术的回顾

1. 多线程的创建(两种)

  1. 通过创建线程对象,复写run(),通过start()调用该线程。

本质是继承

Thread thread = new Thread(){
     	@Override
        public void run() {...}
    };
 thread.start();
  1. 通过有参构造创建线程对象,复写run(),通过start()调用该线程。

本质是接口实现Runnable

 Thread  thread2 = new Thread(new Runnable() {
           @Override
           public void run() {...}
 });
thread2.start();
  • 源码
  • 首先进入构造方法中看见init方法
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
通过对成员变量的target的赋值,就能实现多线程。

2. 线程池的创立

传统的线程创建,寿命只有从线程对象的确定,以及到线程代码的结束,如果一个程序需要不同的时间,创建大量不同的线程,用上述的两种方式创建线程,太过于消耗内存资源。由此引入新的的技术

  • 线程池技术

线程池的创立都是通过Executors创建,通过代理实现不同类型线程池的创建,
线程池都是通过不同的队列的实现,(LinkedBlockingQueue,SynchronousQueue)

//        固定线程数
 ExecutorService threadPool = Executors.newFixedThreadPool(3);
//        根据任务调度线程数(首选,当它回收旧线程时,停止创建新线程,在使用出问题时,才使用newFixedThreadPool)
 ExecutorService threadPool = Executors.newCachedThreadPool();
//       单线程池像是newFixedThreadPool(1);在处理单线程同步问题的时候,可以减少对同步复杂性,因为只有一个线程执行,就不存在同步的可能
ExecutorService threadPool = Executors.newSingleThreadExecutor();

常用的API

  • execute(Runnable command ) 线程调用线程池资源的核心
  • Thread.CurrentThread()获得当前线程对象
  • shutdownNow()
  • shutdown();
    例子
ExecutorService threadPool = Executors.newSingleThreadExecutor();
       for (int i = 0; i < 10; i++) {
           final int task = i;
           threadPool.execute(new Runnable() {
               @Override
               public void run() { }
               }
           });
       }
       System.out.println("shutdown");
       threadPool.shutdownNow();
2.1 从任务中的返回值
  • Runnable是执行工作的独立任务,但是它不返回值,如希望在任务完成时能返回一个值,那么可以实现Callable接口而不是Runnable接口。Callable是一种具有类型参数的泛型,它的类型参数表示的是从call()而不是run()中返回的值,并且使用ExecutorService.submit()方法调用它
class TaskWithResult implements Callable<String>{
	private int id;
	public TaskWithResult(int id){
		this.id = id;
	}
	public String call(){
		return "result of TaskWithResult"+id;
	}
}
public class CallableDemo{
	public static void main(String[] args){
		ExecutorService exec = Executors.newCacheThreadPool();
		List<Future<String>> result  = new ArrayList<>();
		for(int i  = 0;i<10;i++){
			result.add(exec.submit(new TaskWithResult(1)));
		}
		for(Future<String> fs : result){
			try{
				System.out.println(fs.get());
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				exec.shutdown();
			}
		}
	}
}
  • submit()方法会产生Future对象,它用Callable返回结果的特定类型进行了参数化,可以用isDone()查询Future是否完成,若完成,那么就有一个结果,通过get()获取,若未完成,直接用get()方法获取,则会阻塞,直至结果就绪。 一般先用isDone()判断是否完成,再用get
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章