首先,实现线程有三种方式,
1、继承Thread类
2、实现Runnable接口
3、实现Callable接口(个人感觉用的很少)
第一种方式:编写一个类继承Thread类,重写run方法,在测试中直接创建这个类的对象,调用start方法,就可以开启线程啦
第二种方式:编写一个类实现Runnable接口,重写run方法,但是这个是不能直接调用start方法的,因为Runnable没有strat方法,要开启线程需要,new一个Thread对象,把实现Runnable接口的类传入Thread类,之后在调用start方法,开启线程
第三种方式:比第二种又多一个new的对象
在接触线程,必不可少的是解决并发的问题,解决并发的方式也是有三种
1、使用同步代码块,
synchronized(任意对象)
2、使用同步方法
就是在定义方法的前面加上synchronized关键字,例如
public synchronized boolean getThread(){}
3、是在jdk5之后新加的一个方法,lock锁,但是lock是没法创建对象的,利用它的实现类
ReentrantLock来创建lock锁
lock锁开启的方式:ReentrantLock对象.lock
lock锁关闭的方式:ReentrantLock对象.unlock
需要注意的一点是,在使用lock锁的时候,一定要把关锁放在try cath finally中,避免因异常的发生,导致锁没有被关掉,造成线程阻塞
线程池,在网上翻看的时候,发现一句话,阿里巴巴java开发手册上强调说,避免使用jvm自带的线程池,而是用ThreadPoolExecutor,是为了避免资源耗尽的风险
ThreadPoolExecutor:的参数
// 参数一:核心线程数量(不能被销毁)
// 参数二:最大线程数
// 参数三:空闲线程最大存活时间
// 参数四:时间单位(TimeUnit(Time工具类).SECONDS)
// 参数五:任务队列(排队的任务)
// 参数六:创建线程工厂
// 参数七:任务的拒绝策略
//自定义线程池 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, 20, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy() );
注:明确线程池对最多可执行的任务数 = 队列容量 + 最大线程数
慢慢总结,慢慢打工