创建线程有四种方式,继承Thread类、实现Runnable接口、实现Callable接口、线程池创建线程,常用的还是线程池创建线程。
1.继承Thread类
自定义类MyThread(叫什么都行)去extends Thread
重写里面的run方法,new MyThread()去创建多个MyThread对象t1、t2、....
调用start方法启动线程t1.start()、...
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("MyThread...run...");
}
public static void main(String[] args) {
// 创建MyThread对象
MyThread t1 = new MyThread() ;
MyThread t2 = new MyThread() ;
// 调用start方法启动线程
t1.start();
t2.start();
}
}
2.实现Runnable接口
自定义类MyRunnable去implement实现Runnable
重写里面的run方法,创建MyRunnable对象mr,再根据MyRunnable对象创建Thread对象
new Thread(mr)创建t1、t2、....
再调用start方法启动线程t1.start()、...
相比上个步骤就多个创建MyRunnable对象
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("MyRunnable...run...");
}
public static void main(String[] args) {
// 创建MyRunnable对象
MyRunnable mr = new MyRunnable() ;
// 创建Thread对象
Thread t1 = new Thread(mr) ;
Thread t2 = new Thread(mr) ;
// 调用start方法启动线程
t1.start();
t2.start();
}
}
3.实现Callable接口
自定义类MyCallable去implement实现 Callable<里面返回值类型>
重写call()方法,(这里不是重写run方法),需return 返回值(按返回值类型返回)
创建MyCallable对象mc,在根据mc创建未来值对象,new FutureTask<返回值类型>(mc)创建未来值ft,再根据未来值创建线程,new Thread(ft),再调用start方法启动即可,并且可通过未来值ft的get方法获取执行结果
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("MyCallable...call...");
return "OK";
}
public static void main(String[] args) throws
ExecutionException, InterruptedException {
// 创建MyCallable对象
MyCallable mc = new MyCallable() ;
// 创建F
FutureTask<String> ft = new FutureTask<String>(mc) ;
// 创建Thread对象
Thread t1 = new Thread(ft) ;
Thread t2 = new Thread(ft) ;
// 调用start方法启动线程
t1.start();
// 调用ft的get方法获取执行结果
String result = ft.get();
// 输出
System.out.println(result);
}
}
4.利用线程池工具类创建线程
public class MyExecutors implements Runnable{
@Override
public void run() {
System.out.println("MyRunnable...run...");
}
public static void main(String[] args) {
ExecutorService threadPool =
Executors.newFixedThreadPool(3);
threadPool.submit(new MyExecutors()) ;
// 关闭线程池
threadPool.shutdown();
}
}
Executors是线程的工具类,有很多静态方法可以创建线程池对象,但是底层都是通过线程池的实现类ThreadPoolExecutor创建线程池对象,但是使用工具类创建线程池对象存在系统风险.
利用ThreadPoolExecutor创建线程池
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
线程池在创建的时候最大支持传入7个参数,分别是:1.核心线程数 2.最大线程数 3.临时线程空闲时间 4.临时线程空闲时间单位 5.工作队列 6.创建线程的工厂 7.线程池拒绝策略
其中工作队列又叫阻塞队列,指的是当核心线程数已满,新任务到达时,存储线程的队列,常见的有下面几种:基于数组结构的有界阻塞队列ArrayBlockingQueue、基于链表结构的有界阻塞队列LinkedBlockingQueue、具有有限级别的阻塞队列PriorityBlockingQueue、不储存元素的阻塞队列,每个插入操作都必须等待一个移出操作SynchronousQueue
而拒绝策略是指把任务添加到线程池,线程池拒绝该策略所采取的相应策略,官方提供了4种:默认策略,直接抛出异常AbortPolicy、调用者所在线程来执行任务CallerRunsPolicy、丢弃阻塞队列中最靠前的任务并执行当前任务DiscardOldestPolicy、直接丢弃任务DiscardPolicy