多线程总结

一、线程与进程

1.线程与进程的定义

进程:一个操作系统中会可以同时运行多个程序,一个程序就是一个进程。

线程:一个程序会并发性的执行多个任务,多个任务组成一个顺序执行流。

并发:区别于并行性,并行性是指同一时刻有多个任务执行;并发指的是在一段时间内一系列的任务轮番执行,但在宏观上是在一个时刻同时执行的。

多线程优势:

  • 进程之间不能共享内存,但线程之间共享内存非常容易。
  • 系统创建进程时需要为该进程重新分配系统资源,但创建线程则代价小很多,因此使用多线程来实现多任务并发比多进程高效的多。
  • Java语言内置了多线程功能支持,而不是单纯地作为底层操作系统的调度方式,从而简化了Java的多线程编程。

二、线程的创建与启动

1. 继承Thread类创建线程类

public class FirstThread extends Thread{
	
	private int i;
	
	//重写run()方法,run()方法的方法体就是线程执行体
	public void run() {
		for( ; i < 100 ; i++) {
			//当线程类继承Thread类时,直接使用this即可获取当前线程
			//Thread对象的getName()方法返回当前线程的名字
			//因此可以直接调用getName()方法返回当前线程的名字
			System.out.println(getName() + " " + i);
			
			/*
			 * 程序可以通过setName(Stirng Name)方法为线程设置名字	
			 * 使用继承Thread类的方法来创建线程类时,多个线程之间无法共享线程类的实例变量
			*/
		}
	}
	
	public static void main(String[] args) {
		for(int i = 0 ; i < 100 ; i++) {
			//调用Thread的currentThread()方法获取当前线程
			System.out.println(Thread.currentThread().getName() 
					+ " " + i);
			
			if(i == 20) {
				//创建并启动第一个线程
				new FirstThread().start();
				//创建并启动第二个线程
				new FirstThread().start();
			}
		}
	}
}

尽管这段代码只是显示的创建并启动了两个线程,但其实在运行的一共三个线程(还有一个主线程); main()方法的方法体就是主线程的线程执行体

2. 实现Runnable接口创建线程类

//通过实现Runnable接口来创建并启动多线程
public class SecondThread implements Runnable {
	
	private int i;

    //run()方法同样是线程执行体
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for( ; i < 100 ; i++) {
			//当线程类实现Runnable接口时
			//如果想获取当前线程,只能用Thread.currentThread()方法
			//这一点上相比较,继承Thread类的做法会更容易,它只需要在this上进行引用即可
			System.out.println(Thread.currentThread().getName() 
					+ " " + i);
		}
	}
	
	public static void main(String[] args) {
        for(int i = 0; i < 100 ; i++) {
        	System.out.println(Thread.currentThread().getName() 
        			+ " " + i);
        	
        	if(i == 20) {
        		SecondThread st = new SecondThread();
        		
        		//通过new Thread(target, name) 方法创建新线程
        		new Thread(st, "新线程1").start();
        		new Thread(st, "新线程2").start();
        	}
        }
    }
}

继承Thread类的对象可代表线程对象;Runnable接口创建的对象只是线程的target,而多个线程可共享一个线程类的实例变量

3. 使用Callable和Future创建线程

public class ThirdThread{
	public static void main(String[] args) {
		//创建Callable对象
		ThirdThread rt = new ThirdThread();
		
		//先使用Lambda表达式创建Callalbe<Integer>对象
		//使用FutureTask来包装Callable对象
		FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)()->{
			int i = 0;
			for( ; i < 100 ; i++) {
				System.out.println(Thread.currentThread().getName()
					+ "的循环变量i的值" + i);
			}
			
			//call()方法可以有返回值
			return i;
		});
		
		for(int i = 0 ; i < 100 ; i++) {
			System.out.println(Thread.currentThread().getName()
					+ "的循环变量i的值" + i);
		
			if(i == 20) {
				//实质还是以Callable对象来创建并启动线程的
				new Thread(task, "有返回值的线程").start();
			}
		}
		
		try {
			//获取线程返回值
			System.out.println("子线程的返回值" + task.get());
		}
		catch(Exception ex){
			ex.printStackTrace();
		}
	}
}

Callable接口是Runnable接口的增强版;Callable接口提供了一个call()的方法,其可以作为线程执行体,其拥有如下特性

  • call()方法可以有返回值;
  • call()方法可以声明抛出异常

Java 5 提供了Future接口来代表Callable接口里的call()方法的返回值,并为Future接口提供了一个FutureTask实现类,该实现类实现了Future接口,并且实现了Runnable接口---可以作为Thread类的target。

Callable接口有泛型限制,其接口里的泛型参数与call()方法返回值类型相同,而且Callalbe接口是函数式接口,因此可以用Lambda表达式创建Callalbe对象。

Future接口提供了几种公共方法来控制它关联的Callalbe任务:

方法 功能
boolean cancel(boolean mayInterruptIfRunning) 取消该Future里关联的Callable任务
V get() 返回Callable任务里的call()方法的返回值
V get(long timeout, TimeUnit unit) 返回Callable任务里的call()方法的返回值
boolean isCancelled() 如果在Callable任务正常完成前被取消,则返回true
boolean isDone() 如果Callable任务已完成,则返回true
  • V get()方法将导致程序阻塞,必须等到子线程结束后才会得到返回值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值