目录
三、通过Callable和Future创建线程 (实现Callable接口和实现Runnable接口的区别)
一、继承Thread类
- 继承Thread类,重写run()方法,将所需要完成的任务代码写进run()方法中;
- 创建子类的对象;
- 调用该对象的Strart()方法
// 第一步 继承 Thread类 class Thread1 extends Thread{ @Override public void run(){ // 该线程所需执行的任务代码 System.out.print(Thread.currentThread().getName()+":"+"输出结果\n"); } } public class createThread { public static void main(String[] args){ Thread.currentThread().setName("主线程"); System.out.print(Thread.currentThread().getName()+":"+"输出结果\n"); // 第二步 创建子类对象 Thread1 thread1 = new Thread1(); thread1.setName("新建子线程"); // 第三步 调用对象的start方法 thread1.start(); } }
二、实现Runnable接口
- 实现Runnable接口
- 重写run()方法
- 创建实现Runnable接口的类的对象
- 将实现类的对象传入Thread的构造函数创建一个Thread类型对象
- 对用Thread类型对象的start()方法
// 第一步实现Runnable接口 class Runnable1 implements Runnable{ public void run(){ // 该线程所需执行的任务代码 System.out.print(Thread.currentThread().getName()+":"+"输出结果\n"); } } public class createThreadByRunnable { public static void main(String[] args){ Thread.currentThread().setName("主线程"); System.out.print(Thread.currentThread().getName()+":"+"输出结果\n"); // 第二步,创建实现了Runnable接口的实现类的对象,并将该对象传入Thread的构造函数中, // 从而创建一个Thread类型对象 Thread thread1 = new Thread(new Runnable1()); thread1.setName("新建子线程"); // 调用Thread类型对象的start方法 thread1.start(); } }
⚠️使用Thread和Runnable的区别
- 实现 和 继承 角度的区别
- 二者都是通过new Thread 然后调用start方法启动线程的。
- Thread类 实现了 Runnable接口对其进行了扩展
三、通过Callable和Future创建线程 (实现Callable接口和实现Runnable接口的区别)
- Callable接口类似于Runnable,但是Callable的call方法有返回值,可用于异步处理,可以抛出异常,而run方法没有返回值,也不可以抛出异常。
- 调用Thread的构造函数new Thread(futureTask)的方式来创建FutureTask任务,FutureTask是一个实现了Runnable和Future接口的类。
// 第一步实现Callable接口,并且定义返回值类型 public class Callable1 implements Callable<Integer> { public Integer call() throws Exception { // 该线程所需执行的任务代码 Integer num = 0; for(;num < 10; num++){ System.out.print(Thread.currentThread().getName()+"_"+num+":"+"输出结果\n"); } return num; } public static void main(String[] args){ // Callable1 callable1 = new Callable1(); FutureTask<Integer> futureTask = new FutureTask<Integer>(callable1); Thread.currentThread().setName("主线程"); System.out.print(Thread.currentThread().getName()+":"+"输出结果\n"); // 第二步,调用Thread的构造函数new Thread(futureTask)的方式来创建FutureTask任务 Thread thread1 = new Thread(futureTask); thread1.setName("新建子线程"); // 调用Thread类型对象的start方法 thread1.start(); try{ // 获取FutureTask返回值 futureTask.get(); }catch (Exception e){ System.out.print("获取FutureTask返回值异常"); e.printStackTrace(); } } }
四、使用线程池创建
java提供了一个静态的工厂类来创建不同的线程:Executors;通过静态方法创建出来的线程都实现了ExecutorService接口。常用的方法有:
- newFixedThreadPool(int threads) 创建一个固定数目的线程池
- newCahedThreadPool() 创建一个可缓存的线程池,调用execute方法将重用以前创建的线程,如果没有可用的线程则创建一个新的线程并添加到池中,终止并移除那些已经存在60s未被使用的线程。
订单中心中所使用的是ThreadPoolTaskExecutor类,该类是Spring包下的,是Spring为我们提供的线程池类。
1、使用基于XML配置的方式进行创建。
<bean id="oc2ThreadPool" class="com.xinmei.oc2.config.MdcThreadPoolTaskExecutor"> <!-- 核心线程数 --> <property name="corePoolSize" value="10" /> <!-- 最大线程数 --> <property name="maxPoolSize" value="20" /> <!-- 队列最大长度 >=mainExecutor.maxSize --> <property name="queueCapacity" value="5000" /> <!-- 线程池维护线程所允许的空闲时间 --> <property name="keepAliveSeconds" value="300" /> <!-- 线程池对拒绝任务(无线程可用)的处理策略 --> <property name="rejectedExecutionHandler"> <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" /> </property> <property name="threadPriority" value="1" /> </bean>
2、通过配置类的方式配置线程池,然后注入
@Configuration @EnableConfigurationProperties(value = AsyncSharedItemThreadProperteis.class) public class AnsySharedItemThreadConfig { public static final String ASYN_SHARED_ITEM_THREAD = "sharedItemThreadPool"; @Autowired AsyncSharedItemThreadProperteis asyncSharedItemThreadProperteis; // 用于配置线程具体参数的类。 @Bean(ASYN_SHARED_ITEM_THREAD) public Executor sharedItemThreadPool(){ MdcThreadPoolTaskExecutor executor = new MdcThreadPoolTaskExecutor(); executor.setCorePoolSize(asyncSharedItemThreadProperteis.getCorePoolSize()); executor.setMaxPoolSize(asyncSharedItemThreadProperteis.getMaxPoolSize()); executor.setQueueCapacity(asyncSharedItemThreadProperteis.getQueue()); executor.setKeepAliveSeconds(asyncSharedItemThreadProperteis.getKeepAliveSeconds()); executor.setThreadNamePrefix(asyncSharedItemThreadProperteis.getThreadNamePrefix()); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); return executor; } }
3、或者通过自动注入的方式注入线程池
@Autowired @Qualifier("oc2ThreadPool") private ThreadPoolTaskExecutor threadPoolTaskExecutor; public void demo(){ threadPoolTaskExecutor.execute(()->{ queryOrderInfo(entry.getValue(), orderInfoModels, conditionModel, queryType); countDownLatch.countDown(); }); }
五、在程序中如何杀掉一个线程?
- 线程内调用destroy()方法杀死线程
- 线程外调用destroy()方法杀死线程,但是需要加上java监控,获取线程id,否则不知道该线程是否在执行或者已经执行完成!