【Java】 多线程|线程池|计时器|并发与并行|线程生命周期
(一)、多线程
1、线程创建方式:
(1)继承Thread类
class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; } public void run() { . . . } } PrimeThread p = new PrimeThread(143); p.start();
编码简单,但存在单继承的局限性,不能继承其他类,不便于扩展。
重写的Run方法不能返回执行结果。
不适合需要返回执行结果的场景。
(2)实现Runnble接口
class PrimeRun implements Runnable { long minPrime; PrimeRun(long minPrime) { this.minPrime = minPrime; } public void run() { . . . } } PrimeRun p = new PrimeRun(143); new Thread(p).start();
线程任务类实现接口,便于扩展,但编程多一层包装对象。
重写的Run方法不能返回执行结果。
不适合需要返回执行结果的场景。
(3)实现Callable接口
class PrimeCallable implements Callable<V>{ long minPrime; PrimeCallable (long minPrime) { this.minPrime = minPrime; } public V call() throws Exception{ . . . return V; } } Callable<V> call = new PrimeCallable(143); FutureTask<V> target = new FutureTask<T>(call); new Thread(target ).start(); V result = target.get();
通过实现Callable接口再封装成FutureTask对象来创建任务对象。
线程任务类实现接口,扩展性强,可以在线程执行完毕后通过FutureTask返回执行结果。
编码更加复杂(有点牵强)。
2、线程常用方法
(1)final String getName()
Returns this thread's name.(获取线程名称)
(2)final void setName(String name)
Changes the name of this thread to be equal to the argument name.(设置线程名称)
(3)static Thread currentThread()
Returns a reference to the currently executing thread object.(获取当前线程对象)
没必要为线程设置名称,默认名字即可。
3、线程安全问题
多个线程同事操作同一个共享资源的时候可能出现业务安全问题,称为线程安全问题。
线程同步实现使用加锁,把共享资源上锁,让多线程实现先后依次访问。
(1)同步代码块
synchronized(同步锁对象){操作共享资源的代码}
代码块内容被加锁,代码块执行完毕后自动解锁。
同步锁对象理论上可以是任意唯一对象,但存在每个对象创建都会受与锁对象局限。
实例方法推荐使用this作为锁对象,
静态方法推荐使用字节码(类名.call)作为锁对象。
(2)同步方法
在方法定义时使用synchronized修饰即可。
算是隐式锁对象,将整个方法作为同步代码块。
同步方法默认使用this和类名.call作为锁对象
(3)Lock锁
使用Lock的实现类ReentrantLock创建。
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock();
}
}
}
比synchronized丰富,更加强大。
4、线程通信
通常通过共享一个数据的方式实现,根据数据来决定等待自己或是唤醒别人。
如生产者与消费者模型:生产者线程负责生产数据,消费者线程负责消费生产者生产的数据。
一般要求:生产者线程生产完后唤醒消费者,等待自己,消费者消费完后,唤醒生产者,等待自己。
Object类的等待和唤醒方法:
void wait()
void notify()
void notifyall()
注意:上诉方法应该使用当前同步锁对象进行调用。
(二)、线程池
(1)Interface ExecutorService
通常使用实现类Class ThreadPoolExecutor来创建线程池。
ThreadPoolExecutor(int corePoolSize, //指定线程池数量(核心线程)
int maximumPoolSize, //指定线程池最大数量(临时线程=最大数量-核心线程)
long keepAliveTime, //指定临时线程存活时间
TimeUnit unit, //指定存活时间单位(秒,分,时,天)
BlockingQueue<Runnable> workQueue, //指定任务队列
ThreadFactory threadFactory, //指定使用哪个线程工厂创建线程
RejectedExecutionHandler handler) //指定线程忙并且任务队列满后的策略
临时线程必须是在核心线程占用中并且任务队列满后出现新任务才会创建临时线程。(超负荷的时候才考虑创建临时线程)
RejectedExecutionHandler 策略必须是在核心线程和临时线程都在占用中,并且任务队列满后出现新任务时才会使用。
class PrimeRun implements Runnable { long minPrime; PrimeRun(long minPrime) { this.minPrime = minPrime; } public void run() { . . . } } ExecutorService pool = new ThreadPoolExecutor(3,5, 6,TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); PrimeRun p = new PrimeRun(143); pool.execute(p);
使用默认线程工厂并且使用默认新任务拒绝策略。
新任务拒绝策略
1.ThreadPoolExecutor.AbortPolicy() //丢弃任务并抛出RejectedExecutionException异常,默认策略。
2.ThreadPoolExecutor.DiscardPolicy() //丢弃任务,但不抛异常,不推荐
3.ThreadPoolExecutor.DiscardOldestPolicy() //抛弃队列中等待最久的任务,然后把新任务加入队列中
4.ThreadPoolExecutor.CallerRunsPolicy() //由主线程负责对调用任务的run()方法,从而绕过线程池直接执行
ExecutorService的常用方法
1 void execute(Runnable command)
2 Future<?> submit(Runnable task)
void shutdown()
List<Runnable> shutdownNow()
(2)Class Executors
(1)static ExecutorService newCachedThreadPool()(2)static ExecutorService newFixedThreadPool(int nThreads)
static ExecutorService newSingleThreadExecutor()
static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
(三)、定时器
(1)Class Timer
构造方法:
Timer() Creates a new timer.周期调度方法
void schedule(TimerTask task, long delay, long period)(2)Interface ScheduledExecutorService
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2); pool.scheduleAtFixedRate(new TimerTask() { @Override public void run() { //定时任务 ... } }, 2, 2, TimeUnit.SECONDS); //延迟多久时间后开始执行,周期延迟时间,延迟时间单位。
使用Executors的方法创建线程池对象。
static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
使用ScheduledExecutorService的周期调度方法
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)(四)、并发与并行
正在运行的程序就是一个独立的进程,线程是属于进程的,多个线程其实是并发与并行同时进行的。
CPU同时处理线程的数量是有限的,所以会轮询为系统的每个线程服务,由于CPU切换的速度很快,感觉是同时执行,这就是并发。
CPU核数不同,多核同时执行多个任务,这就是并行。
并发:CPU轮询的执行线程。
并行:同一时间同时执行。
(五)、线程生命周期
public enum State { /** * Thread state for a thread which has not yet started. */ NEW, /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */ RUNNABLE, /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */ BLOCKED, /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called {@code Object.wait()} * on an object is waiting for another thread to call * {@code Object.notify()} or {@code Object.notifyAll()} on * that object. A thread that has called {@code Thread.join()} * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }
NEW 线程新建状态
(New新建)线程刚被创建,但是并未启动。
RUNNABLE 可运行状态
(Runnable可运行)线程已经调用了start()等待CPU调度。
BLOCKED Blocked锁阻塞状态
(Blocked锁阻塞)线程在执行的时候未竞争到锁对象,则该线程进入Blocked状态。
WAITING 无线等待状态
(Waiting无线等待)一个线程进入Waiting状态,另一个线程调用notify或者notifyAll方法才能够唤醒。
TIMED_WAITING 被终止状态
(Timed Waiting计时等待)通waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。带有超时参数的常用方法有Thread,sleep、Object.wait。
TERMINATED 计时等待状态
(Teminated被终止)因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。
截图来自网络。


浙公网安备 33010602011771号