Java基础——线程池的使用

线程使用的优化

原因

1、一个线程大致需要1MB的内存空间,如果线程无法回收,那么会导致程序出现内存溢出异常
2、如果线程可以被回收,大量的回收线程会导致系统的负担较大,导致降低程序的执行效率

解决方案:线程池

简介:
	多个线程的容器,可以用来管理其中的线程
优点:
	1、可以设定线程的上限
	2、会复用线程,在线程池中挑选一个暂时没有执行任务的线程对象,使用该对象执行新任务
	3、避免频繁的创建与销毁线程
	4、无须操心线程的创建与销毁,只需给其添加所需执行的任务

线程池的体系结构

Executor(接口)
	方法:void executor(Runnable command);执行任务
	子类或子接口
		ExecutorService(接口)
			方法:
				void shutdown();关闭线程池
				Future<?> sumbit(Runnable task);给线程池提交要执行的任务
			子类:
				ThreadPoolExecutor(类)
					注意:该类创建时需要传入多个对象,导致创建难度较大
					子类:
						ScheduledThreadPoolExecutor(l类)

Executors工具类

作用:帮你创建线程池

常用方法:
	1、创建一个固定长度的线程池,该线程池中线程数量恒定
		public static ExecutorService newFixedThreadPool(int nThreads)
		参数:线程池中的线程数量
	2、创建一个缓存线程池,该线程池中的线程数量由任务数量决定
		public static ExecutorService newCachedThreadPool()
		该线程池中闲置的线程会在60秒后被回收,如果闲置线程在60秒内,有任务需要执行,就直接使用该线程
	3、创建一个单例线程池,该线程池中只有一条线程
		public static ScheduledExecutorService newSingleThreadScheduledExecutor()
	4、创建一个抢占线程池,jdk1.8提供(了解)
		public static ExecutorService newWorkStealingPool()
		1、该线程池中的任务不按顺序执行
		2、该线程池中含有窃取算法
		3、适合于超级耗时的任务
		4、该线程池中所有线程都是守护线程
		
	5、创建一个调度线程池,该线程池中线程数量恒定(掌握)
		public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
		参数:线程池中线程数量
	6、创建一个单例调度线程池,该线程池中只有一条线程(了解)
		public static ScheduledExecutorService newSingleThreadScheduledExecutor()
调度线程池特有的方法ScheduledThreadPoolExecutor
延迟执行:
	
延迟后重复调用:
	public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit);
    参数:
    	command:要执行的任务
    	initialDelay:延迟时间
    	period:重复执行的间隔时间
    		计算规则:前一次任务开始时间与本次任务开始时间的间隔
    			如果前一次任务执行时间<间隔时间,延迟间隔时间-前一次任务执行时间后执行本次任务
    			如果前一次任务执行时间>=间隔时间,那么当前一次任务执行完毕后,直接执行本次任务
    	unit:时间单位
	public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);
                                     
	参数:
		command:要执行的任务
		initialDelay:延迟时间
		delay:重复执行的间隔时间
			计算规则:前一次任务结束时间与本次任务开始时间的间隔
		unit:时间单位

Callable接口

简介

作用:回调,当任务执行完毕后,可以使用其对象在其他线程中获取其返回值

使用

1、与线程结合使用
	步骤:
		1、创建Callable接口对象
		2、使用FutureTask包裹Callable接口对象
		3、创建线程对象传入FutureTask对象
		4、启动线程
		5、使用FutureTask对象获取结果
2、与线程池结合使用
	步骤:
		1、创建Callable接口对象
		2、创建线程池对象
		3、使用线程池对象调用submit方法传图其Callable对象
		4、使用submit方法返回值,调用get方法获取任务结果

Callable与Runnable的区别

1、Callable接口中call方法有返回值,Runnable接口中run方法没有返回值
2、Callable接口中call方法有异常声明,Runnable接口中run方法没有异常声明
3、Callable接口对象不能直接配合Thread对象使用,Runnable接口对象可以直接与Thread对象配合使用
练习:同时拼接an,mz,最终拼接两个结果并输出
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 *练习:同时拼接a~n,m~z,最终拼接两个结果并输出
 *a~n:97~110
 *m~z:109~122
 */
public class Test {
	public static void main(String[] args) {
		ExecutorService service = Executors.newFixedThreadPool(2);
		AddCallable callable01 = new AddCallable(97, 110);
		AddCallable callable02 = new AddCallable(109, 122);
		
		Future<String> submit01 = service.submit(callable01);
		Future<String> submit02 = service.submit(callable02);
		
		service.shutdown();
		
		try {
			String string01 = submit01.get();
			String string02 = submit02.get();
			System.out.println(string01+string02);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
class AddCallable implements Callable<String>{
	private int start;
	private int end;
	
	public AddCallable(int start, int end) {
		this.start = start;
		this.end = end;
	}

	@Override
	public String call() throws Exception {
		StringBuffer buffer = new StringBuffer();
		for (int i = start; i <= end; i++) {
			char c = (char) i;
			buffer.append(c+"");
		}
		return buffer.toString();
	}
	
}

锁的体系结构

Lock(接口)
	方法:
		lock():关闭锁
		unlock():打开锁
	子类:
		ReentrantLock:重写锁
ReentrantLock(接口)
	方法:
		writeLock():获取写的锁对象
		readLock():获取读的锁对象
	子类:
		ReentrantReadWriteLock:读写锁
			该类中提供了两个对象
				WriteLock对象,写锁
				ReadLock对象,读锁
				这两个类又实现了Lock接口
	特性:
		写——写:同步
		读——写:同步
		读——读:异步
作业1:使用线程池完成生产者与消费者模式

作业2:使用线程池与Callable接口完成10的阶乘结果+1~50和的结果。(10的阶乘:10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1)
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Test02 {
	public static void main(String[] args) {
		SumCallable01 sumCallable01 = new SumCallable01(1, 50);
		SumCallable02 sumCallable02 = new SumCallable02(1, 10);
		
		ExecutorService service = Executors.newFixedThreadPool(2);
		Future<Integer> submit01 = service.submit(sumCallable01);
		Future<Integer> submit02 = service.submit(sumCallable02);
		
		try {
			Integer integer01 = submit01.get();
			Integer integer02 = submit02.get();
			System.out.println("1~50的和为:"+integer01);
			System.out.println("10的阶乘为:"+integer02);
			System.out.println("10的阶乘+1~50和的结果为"+(integer01+integer02));
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
//计算1~50的和
class SumCallable01 implements Callable<Integer>{
	private int start;
	private int end;

	public SumCallable01(int start, int end) {
		this.start = start;
		this.end = end;
	}

	@Override
	public Integer call() throws Exception {
		int sum01 = 0;
		int sum02 = 1;
		for (int i = start; i <= end; i++) {
			sum01 += i;
			
		}
		return sum01;
	}
	
}
//计算10的阶乘
class SumCallable02 implements Callable<Integer>{
	private int start;
	private int end;

	public SumCallable02(int start, int end) {
		this.start = start;
		this.end = end;
	}

	@Override
	public Integer call() throws Exception {
		int sum02 = 1;
		for (int i = start; i <= end; i++) {
			sum02 = sum02 * i;
		}
		return sum02;
	}
	
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值