首页 > 其他分享 >线程池

线程池

时间:2023-01-06 19:33:36浏览次数:24  
标签:Runnable 对象 接口 Callable 线程 public

title: 线程池
category: Java
updatedAt: 2022-12-15T09:58:37.209Z
createdAt: 2022-12-15T09:37:21.958Z

线程池介绍:
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);
	}
}

标签:Runnable,对象,接口,Callable,线程,public
From: https://www.cnblogs.com/yuan-autumn/p/17031436.html

相关文章

  • 线程同步3
    线程同步并发同一对象被多个线程同时操作线程同步:处理多线程问题时,多线程访问同一个对象,并且某些线程还想修改这个对象,这时候我们就需要线程同步,线程同步其实就是一种......
  • java多线程创建一个简单的案例
    1、创建一个简单的线程,不需要去创建个RunnableThreadthread=newThread(newRunnable(){@Overridepublicvoidrun(){//todo你要执行的方法}......
  • 【Java】线程池梳理
    【Java】线程池梳理前言线程池:本质上是一种对象池,用于管理线程资源。在任务执行前,需要从线程池中拿出线程来执行。在任务执行完成之后,需要把线程放回线程池。通过线程的......
  • 多线程
    一、多线程概述1.1进程和线程概述进程:操作系统中的应用程序,一个进程就是一个应用程序。进程A和进程B的内存独立不共享资源。线程:CPU调度的最小单元,进程的一个执行流/......
  • 线程状态2
    线程状态2五大状态停止线程线程方法线程停止packagethread;//测试stop/*建议线程正常停止————利用次数不建议是循环*建议使用标志位,设置一个标志位*......
  • android基础02 - 多媒体、多线程与异步任务、Service、网络
    多媒体通知通知渠道:程序对自己发出的通知进行分类,用户可根据渠道对消息进行屏蔽或设置响铃振动。一个应用的通知渠道一旦创建就无法再修改,只能再创建新的可在Activity、......
  • java中的多线程
    一.线程的创建线程的创建方式有两种:一种是继承Thread类,重写run()方法【这里的run()方法只是普通的方法】,在主方法中,创建该类的对象,调用对象的start()方法。二种是实现R......
  • 线程7 - 线程安全问题
    线程安全问题多个线程并发执行时,修改了共享内存中共享对象的属性,导致数据冲突问题线程t1和线程t2都修改和读取同一个对象user,由于并发执行,t1写入后没有直接读取,此时......
  • C# 多线程学习笔记
     ///进程:程序在服务器上运行是,占据的计算资源合集,称之为进程;///进程之间不会相互干扰--进程之间的通信比较困难(分布式)///线程:程序执行的最小单位,相应操作的最小执......
  • 判断线程栈爆掉的一种方法
    就是TEB::StackBase-TEB::StackLimit的值约为线程栈保留大小(VC++编译器默认的是1M),就可以判断栈爆掉了。比如:!tebTEBat01192000   ExceptionList:       ......