本章从实际代码出发,分析一下线程创建的4种方式:
- Runnable
- Thread
- Callable
- ExecutorService
希望读者最后能够明白4种方式的区别与联系,理解线程池管理的优势。
线程创建的4种方式
Runnable创建线程
这种是最常用,最基本的创建线程的方式。
Runnable是线程接口,通过实现Runnable接口,并重写run()方法,即可实现线程类,实例化后,通过start()方法启动线程。
public static void main(String[] args)
{	
	System.out.println(Thread.currentThread().getName()+" is Running");
	new Thread((new Create()).new  MyRunnable(),"线程1").start();
}
public class MyRunnable implements Runnable
{
	@Override
	public void run() {
		try {
			Thread.sleep(500);//单位ms
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+" is Running");
	}
}
Thread创建线程
Thread是线程类,是Runnable的一种实现。
所有的Runnable的实现都必须转化为Thread类,才能够启动!
public static void main(String[] args)
{	
	new Thread((new Create()).new  MyThread(),"线程2").start();
}
public class MyThread extends Thread
{
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+" is Running");
	}
}
创建有返回值的线程
Callable是类似Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他线程执行的任务。 但是与Runnable不同的是,但是Callable创建的线程有返回值,用Future保存。 实现Callable的类需要重写call()方法。最后转换为FutureTask -> Thread(future) 通过start()启动线程, 或者通过线程池submit()方法启动!
public static void main(String[] args)
{
	Future<String> future1=pool.submit(new MyThread());
	try {
		Thread.sleep(100);
		System.out.println("返回值为:"+future1.get().toString());
	} catch (Exception e) {
		e.printStackTrace();
	}
}
public static class MyThread implements Callable <String>
{
	@Override
	public String call() throws Exception {
		return "我是返回值!";
	}
	
}
线程池管理线程
线程池为大量线程的同时运行提供环境,提供调度管理。 线程池通过接收上述3种方式创建的线程作为参数,进而以每个线程作为调度单位进行调度~
线程池的创建分2大类:
- 1:单次运行
- 2:周期调度
每一个又可以细分为3小类:
- 1:单个线程调度
- 2:n个线程调度
- 3:自动调整大小的线程池
public static void main(String[] arg)
{
	//单次调度
//	ExecutorService pool=Executors.newSingleThreadExecutor();//单个线程的线程池
//	ExecutorService pool=Executors.newFixedThreadPool(2);//最大同时运行2个线程池
//	ExecutorService pool=Executors.newCachedThreadPool();//自动调整大小的线程池
			
	//周期调度线程
//	ScheduledExecutorService  pool=Executors.newSingleThreadScheduledExecutor();//单个周期线程的线程池
	ScheduledExecutorService  pool=Executors.newScheduledThreadPool(2);//2个周期线程的线程池
	
	pool.scheduleAtFixedRate(new Thread(new MyRunnable(),"t1"),1,1,TimeUnit.SECONDS);//设置调用周期
	
	pool.execute(new Thread(new MyRunnable(),"t1"));
	pool.execute(new Thread(new MyRunnable(),"t2"));
	pool.execute(new Thread(new MyRunnable(),"t3"));
//	pool.shutdown();
	System.out.println("hello");
}
public static class MyRunnable implements Runnable
{
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+" is Running");
	}
}
Runnable&Thread创建线程区别:
1:前者方便实现数据共享;
2:前者避免了Java单继承的局限性,可以继承多个接口。
上一章: 类&包等名词解释
下一章: 线程调度的6+6