本章从实际代码出发,分析一下线程创建的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