Java之高级多线程(线程池)

线程组ThreadGroup

  • 一个线程的集合,线程组中包含很多个线程,每一个线程默认的线程组名称:main
  • 线程组还可以包括其他线程组。 线程组形成一个树,除了初始线程组之外,每个线程组都有一个父进程。
  • 允许线程访问有关其线程组的信息,但不能访问有关其线程组的父线程组或任何其他线程组的信息。

构造方法

//源码
		 public ThreadGroup(String name) {
        		this(Thread.currentThread().getThreadGroup(), name);
    	 }

常用方法

  • public final ThreadGroup getThreadGroup():获取当前线程所属的线程组
  • public final String getName() :获取线程组名称

线程池

线程出现的问题

  • 线程是宝贵的内存资源,单个线程占1MB空间,过多分配易造成内存溢出
  • 频繁的创建及销毁线程会增加虚拟机回收频率、资源开销、造成程序性能下降
  • 因此线程池出现了

线程池的概念

  • 线程容器,可设定线程分配的数量上限
  • 将预先创建的线程对象存入池中,并重用线程池中的线程对象
  • 避免频繁的创建和销毁

线程池的原理
在这里插入图片描述

获取线程池
在这里插入图片描述
创建线程池

public class TestThreadPool {
	public static void main(String[] args) {
		//	1.	创建固定线程个数的线程池对象
		//线程池里可存在4个线程
		ExecutorService es = Executors.newFixedThreadPool(4);
		//	2.	创建任务
		Runnable runnable = new Runnable() {
			private int ticket = 100;
			
			@Override
			public void run() {
				while (true) {
					if(ticket <= 0) {
						break;
					}
					System.out.println(Thread.currentThread().getName() + "买了" + ticket--);
				}
			}
		};
		//	3.	提交任务
		for(int i = 0; i < 5; i++) {
			es.submit(runnable);
		}
		//	4.	关闭线程池
		es.shutdown();
	}
}

执行结果
在这里插入图片描述

//	1.	创建单线程的线程池
		ExecutorService es = Executors.newSingleThreadExecutor();
//	1.	创建缓冲线程池,线程的个数由任务来决定
		ExecutorService es = Executors.newCachedThreadPool();

Callable接口

public interface Callable<V>{
	public V call() throws Exception;
}
  • JDK5加入,与Runnable接口类似,实现之后代表一个线程任务
  • Callable具有泛型返回值、可以声明异常

Future接口

  • 概念:异步接受ExecutorService.submit()所返回的状态结果,当中包含了call()的返回值
  • 方法:V get()以阻塞形式等待Future中的异步处理结果(call()的返回值)

示例

  • 使用Future和Callable接口
  • 使用两个线程,并发计算1-50,51-100的和,再进行汇总
//示例
public class TestCallable {
	public static void main(String[] args) throws Exception {
		//	1.创建线程池对象
		ExecutorService es = Executors.newFixedThreadPool(2);
		//	2.	提交任务并得到Future对象,任务有Callable匿名对象来承担
		Future<Integer> future1 = es.submit(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {	
				//完成1-50的加和运算并得到结果
				System.out.println("start 1-50 count...");
				int sum = 0;
				for(int i = 1; i <= 50; i++) {
					sum += i;
				}
				return sum;
			}
		});
		Future<Integer> future2 = es.submit(new Callable<Integer>() {	
			@Override
			public Integer call() throws Exception {	
				//完成51-100的加和运算并得到结果
				System.out.println("start 51 - 100 count...");
				int sum = 0;
				for(int i = 51; i <= 100; i++) {
					sum += i;
				}
				return sum;
			}
		});
			
		//	3.	使用Future对象的get()方法得到运算结果
		System.out.println("1-100的加和结果为:" + (future1.get() + future2.get()));
			
		//	4.	关闭资源
		es.shutdown();
	}
}

结果
在这里插入图片描述

Lock接口

  • JDK5加入,与synchronized比较,显示定义,结构更灵活
  • 提供更多实用性方法,功能更加强大,性能更优越

常用方法

//获取锁,如锁被占用,则等待
void lock()   
//尝试获取锁(成功true,失败false,不阻塞)
boolean tryLock
//释放锁
void unlock()
//示例
public class TestLock implements Runnable {
	Lock l = new ReentrantLock();
	private int ticket = 100;

	@Override
	public void run() {
		while (true) {
			l.lock();
			
			try {
				if(ticket <= 0) {
					break;
				}
				
				System.out.println(Thread.currentThread().getName() +  " sells " + ticket--);
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				l.unlock();
			}
		}
	}

	public static void main(String[] args) {
		
		ExecutorService es = Executors.newFixedThreadPool(4);
		
		for(int i = 0; i < 4; i++) {
			es.submit(new TestLock());
		}
		
		es.shutdown();
	}
}

执行结果
在这里插入图片描述

线程安全的集合
在这里插入图片描述
Collections中的工具方法
在这里插入图片描述
Queue接口(队列)
在这里插入图片描述

//示例
public class TestQueue {

	public static void main(String[] args) {
		
		//	1.	创建PriorityQueue队列对象
		PriorityQueue<String> q = new PriorityQueue<String>();
		
		//	2.	队列添加元素,“入列”
		q.offer("a");
		q.offer("b");
		q.offer("c");
		q.offer("d");
		q.offer("e");
		
		//	3.	取值,“出列”
		System.out.println(q.poll());
		System.out.println(q.poll());
		System.out.println(q.poll());
		System.out.println(q.poll());
		System.out.println(q.poll());
	}
}

执行结果
在这里插入图片描述

定时器工具:java.util.Timer

  • 可以重复执行某个任务/或者执行一次任务

构造方法

  • public Timer():构造一个新的计时器

TimerTask

  • 由定时器Timer来安排是执行一次/重复执行当前任务
  • public abstract void run():任务要执行的操作

成员方法:

//终止定时器
public void cancel()
//在指定日期时间内容将执行这个 任务!
public void schedule(TimerTask task,Date time)
//在指定时间后执行当前这个task任务
public void schedule(TimerTask task, long delay)
//在某个时间内容执行这个任务,然后每经过period时间毫秒值后重复执行任务!
public void schedule(TimerTask task, long delay,long period)

示例

public class TimerDemo {
	
	public static void main(String[] args) {
		
		//创建一个定时器
		Timer timer = new Timer() ;
		
		// public void schedule(TimerTask task, long delay) 
//		timer.schedule(new MyTask(), 3000);
		//开启定时任务的同时,时间到了,取消定时器
		//timer.schedule(new MyTask(timer), 3000);

		
//		public void schedule(TimerTask task, long delay,long period)
		timer.schedule(new MyTask(), 2000, 3000);
	}
}

//自定义一个类:继承自TimerTask:定时任务
class MyTask extends TimerTask{
	
	//在成员位置声明一个定时器类型变量
	private Timer t ;
	public MyTask() {
		
	}
	public MyTask(Timer t) {
		this.t = t ;
	}
	
	@Override
	public void run() {
		System.out.println("bom...爆炸了...");
		//取消定时器
		//t.cancel();
	}
}

示例,在某个时间,删除指定文件

public class Demo05 {
	
	public static void main(String[] args) throws ParseException {
		
		String source = "2020-11-2 19:56:00";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date date = sdf.parse(source);
		
		Timer timer = new Timer();
		timer.schedule(new TimerTask() {
			
			@Override
			public void run() {
				File file = new File("C:\\Users\\demo");
				File[] files = file.listFiles();
				for (File f : files) {
					System.out.println("删除了"+f.getName()+"文件");
					f.delete();	
				}
			}
		}, date);
		
		

		
	}
	

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值