线程池

线程池介绍:
Java里面线程池的顶级接口是java.util.concurrent.Executor,以及他的子接口java.util.concurrent.ExecutorService

要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在java.util.concurrent.Executors线程工厂类里面提供了一些静态工厂,生成一些常用的线程池。官方建议使用Executors工程类来创建线程池对象。
Executors类中有个创建线程池的方法如下:

  • public static ExecutorService newFixedThreadPool(int nThreads):返回线程池对象。(创建的是有界线程池,也就是池中的线程个数可以指定最大数量)

获取到了一个线程池ExecutorService 对象,那么怎么使用呢,在这里定义了一个使用线程池对象的方法如下:

  • public Future<?> submit(Runnable task):获取线程池中的某一个线程对象,并执行

    Future接口:用来记录线程任务执行完毕后产生的结果。

使用线程池中线程对象的步骤:

​ A:自定义一个类,作为任务类并实现Runnable接口;

​ B:实现Runnable接口中的run方法;

​ C:创建任务类的对象;

​ D:获取线程池对象;

​ E:直接执行任务;​

需求:使用线程池来完成卖票任务。

//A:自定义一个类,作为任务类并实现Runnable接口;
class SellTicketTask implements Runnable
{
	//定义成员变量存储100张票
	private static int tickets=100;
	//创建锁对象
	private Lock l=new ReentrantLock();
	//B:实现Runnable接口中的run方法;
	public void run() {
		// 模拟卖票
		while(true)
		{
			//获取锁
			l.lock();
			if(tickets>0)
			{
				//休眠
				try {
					Thread.sleep(1);
				} catch (InterruptedException e) {
				}
				System.out.println(Thread.currentThread().getName()+"出票:"+tickets);
                  tickets--;
			}
			//释放锁
			l.unlock();
		}
	}
}
-------
public class SellTicketDemo {
	public static void main(String[] args) {
		//C:创建任务类的对象;
		SellTicketTask stt = new SellTicketTask();
		//D:获取线程池对象; 获取2个线程
		ExecutorService es = Executors.newFixedThreadPool(2);
		//E:直接执行任务; 
      	  //自己创建线程对象的方式
        // Thread t = new Thread(stt);
        // t.start(); ---> 调用MyRunnable中的run()

        // 从线程池中获取线程对象,然后调用SellTicketTask中的run()
        es.submit(stt);
        // 再获取个线程对象,调用SellTicketTask中的run()
        es.submit(stt);
	}
}

Callable测试代码:

  • <T> Future<T> submit(Callable<T> task) : 获取线程池中的某一个线程对象,并执行.

image.png

/*
 * 演示:演示Callable
 * 我们忽略返回值,这个接口就与Runnable接口一样了
 */
class MyTask implements Callable<Object>{

	@Override
	public Object call() throws Exception {
		for( int i = 0; i < 10; i++){
			System.out.println(Thread.currentThread().getName() + " ... " + i);
		}
		return null;
	}
}
public class CallableDemo {
	public static void main(String[] args) {
		// 创建任务对象
		MyTask mt = new MyTask();
		// 获取线程池
		ExecutorService es = Executors.newFixedThreadPool(2);
		// 执行任务
		es.submit(mt);
		es.submit(mt);
	}
}

问题2:Future是什么?

  • 方法:V get() : 获取计算完成的结果。

A:我们自定义类,实现Callable接口

B:实现Call方法,Call方法有返回值

C:然后吧任务类对象交给线程池执行

D:执行完成的结果保存Future中

E:最后我们调用Future的get方法拿到真正的结果。

    /*
 * 演示:带返回值的线程任务
 * 需求:通过Callable计算从1到任意数字的和
 */
class SumTask implements Callable<Integer>{
	
	@Override
	public Integer call() throws Exception {
		int sum = 0;
		for(int i = 1; i <= 5; i++){
			sum += i;
		}
		return sum ;
	}
}
public class CallableDemo02 {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		// 创建任务对象
		SumTask st = new SumTask();
		// 获取线程池
		ExecutorService es = Executors.newFixedThreadPool(1);
		// 执行任务
		Future<Integer> future = es.submit(st);
		// 等待运算结束,获取结果
		Integer i = future.get();
		System.out.println(i);
	}
}
posted @ 2023-01-06 19:24  ionng  阅读(19)  评论(0)    收藏  举报